aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/test/pickletester.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/pickletester.py')
-rw-r--r--Lib/test/pickletester.py1111
1 files changed, 713 insertions, 398 deletions
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index c321f8e78a5..4d491b0173c 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -1,60 +1,30 @@
+import io
import unittest
import pickle
-import cPickle
-import StringIO
-import cStringIO
import pickletools
-import copy_reg
+import sys
+import copyreg
+from http.cookies import SimpleCookie
-from test.test_support import TestFailed, have_unicode, TESTFN
+from test.support import (
+ TestFailed, TESTFN, run_with_locale,
+ _2G, _4G, bigmemtest,
+ )
+
+from pickle import bytes_types
# Tests that try a number of pickle protocols should have a
# for proto in protocols:
# kind of outer loop.
-assert pickle.HIGHEST_PROTOCOL == cPickle.HIGHEST_PROTOCOL == 2
protocols = range(pickle.HIGHEST_PROTOCOL + 1)
-# Copy of test.test_support.run_with_locale. This is needed to support Python
-# 2.4, which didn't include it. This is all to support test_xpickle, which
-# bounces pickled objects through older Python versions to test backwards
-# compatibility.
-def run_with_locale(catstr, *locales):
- def decorator(func):
- def inner(*args, **kwds):
- try:
- import locale
- category = getattr(locale, catstr)
- orig_locale = locale.setlocale(category)
- except AttributeError:
- # if the test author gives us an invalid category string
- raise
- except:
- # cannot retrieve original locale, so do nothing
- locale = orig_locale = None
- else:
- for loc in locales:
- try:
- locale.setlocale(category, loc)
- break
- except:
- pass
-
- # now run the function, resetting the locale on exceptions
- try:
- return func(*args, **kwds)
- finally:
- if locale and orig_locale:
- locale.setlocale(category, orig_locale)
- inner.func_name = func.func_name
- inner.__doc__ = func.__doc__
- return inner
- return decorator
+character_size = 4 if sys.maxunicode > 0xFFFF else 2
# Return True if opcode code appears in the pickle, else False.
def opcode_in_pickle(code, pickle):
for op, dummy, dummy in pickletools.genops(pickle):
- if op.code == code:
+ if op.code == code.decode("latin-1"):
return True
return False
@@ -62,10 +32,25 @@ def opcode_in_pickle(code, pickle):
def count_opcode(code, pickle):
n = 0
for op, dummy, dummy in pickletools.genops(pickle):
- if op.code == code:
+ if op.code == code.decode("latin-1"):
n += 1
return n
+
+class UnseekableIO(io.BytesIO):
+ def peek(self, *args):
+ raise NotImplementedError
+
+ def seekable(self):
+ return False
+
+ def seek(self, *args):
+ raise io.UnsupportedOperation
+
+ def tell(self):
+ raise io.UnsupportedOperation
+
+
# We can't very well test the extension registry without putting known stuff
# in it, but we have to be careful to restore its original state. Code
# should do this:
@@ -81,29 +66,41 @@ class ExtensionSaver:
# there is one).
def __init__(self, code):
self.code = code
- if code in copy_reg._inverted_registry:
- self.pair = copy_reg._inverted_registry[code]
- copy_reg.remove_extension(self.pair[0], self.pair[1], code)
+ if code in copyreg._inverted_registry:
+ self.pair = copyreg._inverted_registry[code]
+ copyreg.remove_extension(self.pair[0], self.pair[1], code)
else:
self.pair = None
# Restore previous registration for code.
def restore(self):
code = self.code
- curpair = copy_reg._inverted_registry.get(code)
+ curpair = copyreg._inverted_registry.get(code)
if curpair is not None:
- copy_reg.remove_extension(curpair[0], curpair[1], code)
+ copyreg.remove_extension(curpair[0], curpair[1], code)
pair = self.pair
if pair is not None:
- copy_reg.add_extension(pair[0], pair[1], code)
+ copyreg.add_extension(pair[0], pair[1], code)
class C:
- def __cmp__(self, other):
- return cmp(self.__dict__, other.__dict__)
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+class D(C):
+ def __init__(self, arg):
+ pass
+
+class E(C):
+ def __getinitargs__(self):
+ return ()
import __main__
__main__.C = C
C.__module__ = "__main__"
+__main__.D = D
+D.__module__ = "__main__"
+__main__.E = E
+E.__module__ = "__main__"
class myint(int):
def __init__(self, x):
@@ -121,8 +118,8 @@ class initarg(C):
class metaclass(type):
pass
-class use_metaclass(object):
- __metaclass__ = metaclass
+class use_metaclass(object, metaclass=metaclass):
+ pass
class pickling_metaclass(type):
def __eq__(self, other):
@@ -132,8 +129,6 @@ class pickling_metaclass(type):
def __reduce__(self):
return (create_dynamic_class, self.reduce_args)
- __hash__ = None
-
def create_dynamic_class(name, bases):
result = pickling_metaclass(name, bases, dict())
result.reduce_args = (name, bases)
@@ -142,262 +137,281 @@ def create_dynamic_class(name, bases):
# DATA0 .. DATA2 are the pickles we expect under the various protocols, for
# the object returned by create_data().
-# break into multiple strings to avoid confusing font-lock-mode
-DATA0 = """(lp1
-I0
-aL1L
-aF2
-ac__builtin__
-complex
-p2
-""" + \
-"""(F3
-F0
-tRp3
-aI1
-aI-1
-aI255
-aI-255
-aI-256
-aI65535
-aI-65535
-aI-65536
-aI2147483647
-aI-2147483647
-aI-2147483648
-a""" + \
-"""(S'abc'
-p4
-g4
-""" + \
-"""(i__main__
-C
-p5
-""" + \
-"""(dp6
-S'foo'
-p7
-I1
-sS'bar'
-p8
-I2
-sbg5
-tp9
-ag9
-aI5
-a.
-"""
-
-# Disassembly of DATA0.
+DATA0 = (
+ b'(lp0\nL0L\naL1L\naF2.0\nac'
+ b'builtins\ncomplex\n'
+ b'p1\n(F3.0\nF0.0\ntp2\nRp'
+ b'3\naL1L\naL-1L\naL255L\naL-'
+ b'255L\naL-256L\naL65535L\na'
+ b'L-65535L\naL-65536L\naL2'
+ b'147483647L\naL-2147483'
+ b'647L\naL-2147483648L\na('
+ b'Vabc\np4\ng4\nccopyreg'
+ b'\n_reconstructor\np5\n('
+ b'c__main__\nC\np6\ncbu'
+ b'iltins\nobject\np7\nNt'
+ b'p8\nRp9\n(dp10\nVfoo\np1'
+ b'1\nL1L\nsVbar\np12\nL2L\nsb'
+ b'g9\ntp13\nag13\naL5L\na.'
+)
+
+# Disassembly of DATA0
DATA0_DIS = """\
0: ( MARK
1: l LIST (MARK at 0)
- 2: p PUT 1
- 5: I INT 0
- 8: a APPEND
- 9: L LONG 1L
- 13: a APPEND
- 14: F FLOAT 2.0
- 17: a APPEND
- 18: c GLOBAL '__builtin__ complex'
- 39: p PUT 2
+ 2: p PUT 0
+ 5: L LONG 0
+ 9: a APPEND
+ 10: L LONG 1
+ 14: a APPEND
+ 15: F FLOAT 2.0
+ 20: a APPEND
+ 21: c GLOBAL 'builtins complex'
+ 39: p PUT 1
42: ( MARK
43: F FLOAT 3.0
- 46: F FLOAT 0.0
- 49: t TUPLE (MARK at 42)
- 50: R REDUCE
- 51: p PUT 3
- 54: a APPEND
- 55: I INT 1
- 58: a APPEND
- 59: I INT -1
- 63: a APPEND
- 64: I INT 255
- 69: a APPEND
- 70: I INT -255
- 76: a APPEND
- 77: I INT -256
- 83: a APPEND
- 84: I INT 65535
- 91: a APPEND
- 92: I INT -65535
- 100: a APPEND
- 101: I INT -65536
- 109: a APPEND
- 110: I INT 2147483647
- 122: a APPEND
- 123: I INT -2147483647
- 136: a APPEND
- 137: I INT -2147483648
- 150: a APPEND
- 151: ( MARK
- 152: S STRING 'abc'
- 159: p PUT 4
- 162: g GET 4
- 165: ( MARK
- 166: i INST '__main__ C' (MARK at 165)
- 178: p PUT 5
- 181: ( MARK
- 182: d DICT (MARK at 181)
- 183: p PUT 6
- 186: S STRING 'foo'
- 193: p PUT 7
- 196: I INT 1
- 199: s SETITEM
- 200: S STRING 'bar'
- 207: p PUT 8
- 210: I INT 2
- 213: s SETITEM
- 214: b BUILD
- 215: g GET 5
- 218: t TUPLE (MARK at 151)
- 219: p PUT 9
- 222: a APPEND
- 223: g GET 9
- 226: a APPEND
- 227: I INT 5
- 230: a APPEND
- 231: . STOP
+ 48: F FLOAT 0.0
+ 53: t TUPLE (MARK at 42)
+ 54: p PUT 2
+ 57: R REDUCE
+ 58: p PUT 3
+ 61: a APPEND
+ 62: L LONG 1
+ 66: a APPEND
+ 67: L LONG -1
+ 72: a APPEND
+ 73: L LONG 255
+ 79: a APPEND
+ 80: L LONG -255
+ 87: a APPEND
+ 88: L LONG -256
+ 95: a APPEND
+ 96: L LONG 65535
+ 104: a APPEND
+ 105: L LONG -65535
+ 114: a APPEND
+ 115: L LONG -65536
+ 124: a APPEND
+ 125: L LONG 2147483647
+ 138: a APPEND
+ 139: L LONG -2147483647
+ 153: a APPEND
+ 154: L LONG -2147483648
+ 168: a APPEND
+ 169: ( MARK
+ 170: V UNICODE 'abc'
+ 175: p PUT 4
+ 178: g GET 4
+ 181: c GLOBAL 'copyreg _reconstructor'
+ 205: p PUT 5
+ 208: ( MARK
+ 209: c GLOBAL '__main__ C'
+ 221: p PUT 6
+ 224: c GLOBAL 'builtins object'
+ 241: p PUT 7
+ 244: N NONE
+ 245: t TUPLE (MARK at 208)
+ 246: p PUT 8
+ 249: R REDUCE
+ 250: p PUT 9
+ 253: ( MARK
+ 254: d DICT (MARK at 253)
+ 255: p PUT 10
+ 259: V UNICODE 'foo'
+ 264: p PUT 11
+ 268: L LONG 1
+ 272: s SETITEM
+ 273: V UNICODE 'bar'
+ 278: p PUT 12
+ 282: L LONG 2
+ 286: s SETITEM
+ 287: b BUILD
+ 288: g GET 9
+ 291: t TUPLE (MARK at 169)
+ 292: p PUT 13
+ 296: a APPEND
+ 297: g GET 13
+ 301: a APPEND
+ 302: L LONG 5
+ 306: a APPEND
+ 307: . STOP
highest protocol among opcodes = 0
"""
-DATA1 = (']q\x01(K\x00L1L\nG@\x00\x00\x00\x00\x00\x00\x00'
- 'c__builtin__\ncomplex\nq\x02(G@\x08\x00\x00\x00\x00\x00'
- '\x00G\x00\x00\x00\x00\x00\x00\x00\x00tRq\x03K\x01J\xff\xff'
- '\xff\xffK\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xff'
- 'J\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00'
- '\x00\x80J\x00\x00\x00\x80(U\x03abcq\x04h\x04(c__main__\n'
- 'C\nq\x05oq\x06}q\x07(U\x03fooq\x08K\x01U\x03barq\tK\x02ubh'
- '\x06tq\nh\nK\x05e.'
- )
-
-# Disassembly of DATA1.
+DATA1 = (
+ b']q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
+ b'builtins\ncomplex\nq\x01'
+ b'(G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00t'
+ b'q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xffJ'
+ b'\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff\xff'
+ b'\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00ab'
+ b'cq\x04h\x04ccopyreg\n_reco'
+ b'nstructor\nq\x05(c__main'
+ b'__\nC\nq\x06cbuiltins\n'
+ b'object\nq\x07Ntq\x08Rq\t}q\n('
+ b'X\x03\x00\x00\x00fooq\x0bK\x01X\x03\x00\x00\x00bar'
+ b'q\x0cK\x02ubh\ttq\rh\rK\x05e.'
+)
+
+# Disassembly of DATA1
DATA1_DIS = """\
0: ] EMPTY_LIST
- 1: q BINPUT 1
+ 1: q BINPUT 0
3: ( MARK
4: K BININT1 0
- 6: L LONG 1L
- 10: G BINFLOAT 2.0
- 19: c GLOBAL '__builtin__ complex'
- 40: q BINPUT 2
- 42: ( MARK
- 43: G BINFLOAT 3.0
- 52: G BINFLOAT 0.0
- 61: t TUPLE (MARK at 42)
- 62: R REDUCE
- 63: q BINPUT 3
- 65: K BININT1 1
- 67: J BININT -1
- 72: K BININT1 255
- 74: J BININT -255
- 79: J BININT -256
- 84: M BININT2 65535
- 87: J BININT -65535
- 92: J BININT -65536
- 97: J BININT 2147483647
- 102: J BININT -2147483647
- 107: J BININT -2147483648
- 112: ( MARK
- 113: U SHORT_BINSTRING 'abc'
+ 6: K BININT1 1
+ 8: G BINFLOAT 2.0
+ 17: c GLOBAL 'builtins complex'
+ 35: q BINPUT 1
+ 37: ( MARK
+ 38: G BINFLOAT 3.0
+ 47: G BINFLOAT 0.0
+ 56: t TUPLE (MARK at 37)
+ 57: q BINPUT 2
+ 59: R REDUCE
+ 60: q BINPUT 3
+ 62: K BININT1 1
+ 64: J BININT -1
+ 69: K BININT1 255
+ 71: J BININT -255
+ 76: J BININT -256
+ 81: M BININT2 65535
+ 84: J BININT -65535
+ 89: J BININT -65536
+ 94: J BININT 2147483647
+ 99: J BININT -2147483647
+ 104: J BININT -2147483648
+ 109: ( MARK
+ 110: X BINUNICODE 'abc'
118: q BINPUT 4
120: h BINGET 4
- 122: ( MARK
- 123: c GLOBAL '__main__ C'
- 135: q BINPUT 5
- 137: o OBJ (MARK at 122)
- 138: q BINPUT 6
- 140: } EMPTY_DICT
- 141: q BINPUT 7
- 143: ( MARK
- 144: U SHORT_BINSTRING 'foo'
- 149: q BINPUT 8
- 151: K BININT1 1
- 153: U SHORT_BINSTRING 'bar'
- 158: q BINPUT 9
- 160: K BININT1 2
- 162: u SETITEMS (MARK at 143)
- 163: b BUILD
- 164: h BINGET 6
- 166: t TUPLE (MARK at 112)
- 167: q BINPUT 10
- 169: h BINGET 10
- 171: K BININT1 5
- 173: e APPENDS (MARK at 3)
- 174: . STOP
+ 122: c GLOBAL 'copyreg _reconstructor'
+ 146: q BINPUT 5
+ 148: ( MARK
+ 149: c GLOBAL '__main__ C'
+ 161: q BINPUT 6
+ 163: c GLOBAL 'builtins object'
+ 180: q BINPUT 7
+ 182: N NONE
+ 183: t TUPLE (MARK at 148)
+ 184: q BINPUT 8
+ 186: R REDUCE
+ 187: q BINPUT 9
+ 189: } EMPTY_DICT
+ 190: q BINPUT 10
+ 192: ( MARK
+ 193: X BINUNICODE 'foo'
+ 201: q BINPUT 11
+ 203: K BININT1 1
+ 205: X BINUNICODE 'bar'
+ 213: q BINPUT 12
+ 215: K BININT1 2
+ 217: u SETITEMS (MARK at 192)
+ 218: b BUILD
+ 219: h BINGET 9
+ 221: t TUPLE (MARK at 109)
+ 222: q BINPUT 13
+ 224: h BINGET 13
+ 226: K BININT1 5
+ 228: e APPENDS (MARK at 3)
+ 229: . STOP
highest protocol among opcodes = 1
"""
-DATA2 = ('\x80\x02]q\x01(K\x00\x8a\x01\x01G@\x00\x00\x00\x00\x00\x00\x00'
- 'c__builtin__\ncomplex\nq\x02G@\x08\x00\x00\x00\x00\x00\x00G\x00'
- '\x00\x00\x00\x00\x00\x00\x00\x86Rq\x03K\x01J\xff\xff\xff\xffK'
- '\xffJ\x01\xff\xff\xffJ\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xff'
- 'J\x00\x00\xff\xffJ\xff\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00'
- '\x80(U\x03abcq\x04h\x04(c__main__\nC\nq\x05oq\x06}q\x07(U\x03foo'
- 'q\x08K\x01U\x03barq\tK\x02ubh\x06tq\nh\nK\x05e.')
-
-# Disassembly of DATA2.
+DATA2 = (
+ b'\x80\x02]q\x00(K\x00K\x01G@\x00\x00\x00\x00\x00\x00\x00c'
+ b'builtins\ncomplex\n'
+ b'q\x01G@\x08\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x86q\x02Rq\x03K\x01J\xff\xff\xff\xffK\xffJ\x01\xff\xff\xff'
+ b'J\x00\xff\xff\xffM\xff\xffJ\x01\x00\xff\xffJ\x00\x00\xff\xffJ\xff'
+ b'\xff\xff\x7fJ\x01\x00\x00\x80J\x00\x00\x00\x80(X\x03\x00\x00\x00a'
+ b'bcq\x04h\x04c__main__\nC\nq\x05'
+ b')\x81q\x06}q\x07(X\x03\x00\x00\x00fooq\x08K\x01'
+ b'X\x03\x00\x00\x00barq\tK\x02ubh\x06tq\nh'
+ b'\nK\x05e.'
+)
+
+# Disassembly of DATA2
DATA2_DIS = """\
0: \x80 PROTO 2
2: ] EMPTY_LIST
- 3: q BINPUT 1
+ 3: q BINPUT 0
5: ( MARK
6: K BININT1 0
- 8: \x8a LONG1 1L
- 11: G BINFLOAT 2.0
- 20: c GLOBAL '__builtin__ complex'
- 41: q BINPUT 2
- 43: G BINFLOAT 3.0
- 52: G BINFLOAT 0.0
- 61: \x86 TUPLE2
- 62: R REDUCE
- 63: q BINPUT 3
- 65: K BININT1 1
- 67: J BININT -1
- 72: K BININT1 255
- 74: J BININT -255
- 79: J BININT -256
- 84: M BININT2 65535
- 87: J BININT -65535
- 92: J BININT -65536
- 97: J BININT 2147483647
- 102: J BININT -2147483647
- 107: J BININT -2147483648
- 112: ( MARK
- 113: U SHORT_BINSTRING 'abc'
- 118: q BINPUT 4
- 120: h BINGET 4
- 122: ( MARK
- 123: c GLOBAL '__main__ C'
- 135: q BINPUT 5
- 137: o OBJ (MARK at 122)
- 138: q BINPUT 6
- 140: } EMPTY_DICT
- 141: q BINPUT 7
- 143: ( MARK
- 144: U SHORT_BINSTRING 'foo'
- 149: q BINPUT 8
- 151: K BININT1 1
- 153: U SHORT_BINSTRING 'bar'
- 158: q BINPUT 9
- 160: K BININT1 2
- 162: u SETITEMS (MARK at 143)
- 163: b BUILD
- 164: h BINGET 6
- 166: t TUPLE (MARK at 112)
- 167: q BINPUT 10
- 169: h BINGET 10
- 171: K BININT1 5
- 173: e APPENDS (MARK at 5)
- 174: . STOP
+ 8: K BININT1 1
+ 10: G BINFLOAT 2.0
+ 19: c GLOBAL 'builtins complex'
+ 37: q BINPUT 1
+ 39: G BINFLOAT 3.0
+ 48: G BINFLOAT 0.0
+ 57: \x86 TUPLE2
+ 58: q BINPUT 2
+ 60: R REDUCE
+ 61: q BINPUT 3
+ 63: K BININT1 1
+ 65: J BININT -1
+ 70: K BININT1 255
+ 72: J BININT -255
+ 77: J BININT -256
+ 82: M BININT2 65535
+ 85: J BININT -65535
+ 90: J BININT -65536
+ 95: J BININT 2147483647
+ 100: J BININT -2147483647
+ 105: J BININT -2147483648
+ 110: ( MARK
+ 111: X BINUNICODE 'abc'
+ 119: q BINPUT 4
+ 121: h BINGET 4
+ 123: c GLOBAL '__main__ C'
+ 135: q BINPUT 5
+ 137: ) EMPTY_TUPLE
+ 138: \x81 NEWOBJ
+ 139: q BINPUT 6
+ 141: } EMPTY_DICT
+ 142: q BINPUT 7
+ 144: ( MARK
+ 145: X BINUNICODE 'foo'
+ 153: q BINPUT 8
+ 155: K BININT1 1
+ 157: X BINUNICODE 'bar'
+ 165: q BINPUT 9
+ 167: K BININT1 2
+ 169: u SETITEMS (MARK at 144)
+ 170: b BUILD
+ 171: h BINGET 6
+ 173: t TUPLE (MARK at 110)
+ 174: q BINPUT 10
+ 176: h BINGET 10
+ 178: K BININT1 5
+ 180: e APPENDS (MARK at 5)
+ 181: . STOP
highest protocol among opcodes = 2
"""
+# set([1,2]) pickled from 2.x with protocol 2
+DATA3 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01(K\x01K\x02e\x85q\x02Rq\x03.'
+
+# xrange(5) pickled from 2.x with protocol 2
+DATA4 = b'\x80\x02c__builtin__\nxrange\nq\x00K\x00K\x05K\x01\x87q\x01Rq\x02.'
+
+# a SimpleCookie() object pickled from 2.x with protocol 2
+DATA5 = (b'\x80\x02cCookie\nSimpleCookie\nq\x00)\x81q\x01U\x03key'
+ b'q\x02cCookie\nMorsel\nq\x03)\x81q\x04(U\x07commentq\x05U'
+ b'\x00q\x06U\x06domainq\x07h\x06U\x06secureq\x08h\x06U\x07'
+ b'expiresq\th\x06U\x07max-ageq\nh\x06U\x07versionq\x0bh\x06U'
+ b'\x04pathq\x0ch\x06U\x08httponlyq\rh\x06u}q\x0e(U\x0b'
+ b'coded_valueq\x0fU\x05valueq\x10h\x10h\x10h\x02h\x02ubs}q\x11b.')
+
+# set([3]) pickled from 2.x with protocol 2
+DATA6 = b'\x80\x02c__builtin__\nset\nq\x00]q\x01K\x03a\x85q\x02Rq\x03.'
+
+
def create_data():
c = C()
c.foo = 1
c.bar = 2
- x = [0, 1L, 2.0, 3.0+0j]
+ x = [0, 1, 2.0, 3.0+0j]
# Append some integer test cases at cPickle.c's internal size
# cutoffs.
uint1max = 0xff
@@ -414,7 +428,7 @@ def create_data():
return x
class AbstractPickleTests(unittest.TestCase):
- # Subclass must define self.dumps, self.loads, self.error.
+ # Subclass must define self.dumps, self.loads.
_testdata = create_data()
@@ -448,11 +462,71 @@ class AbstractPickleTests(unittest.TestCase):
got = self.loads(s)
self.assertEqual(expected, got)
- def test_load_from_canned_string(self):
- expected = self._testdata
- for canned in DATA0, DATA1, DATA2:
- got = self.loads(canned)
- self.assertEqual(expected, got)
+ def test_load_from_data0(self):
+ self.assertEqual(self._testdata, self.loads(DATA0))
+
+ def test_load_from_data1(self):
+ self.assertEqual(self._testdata, self.loads(DATA1))
+
+ def test_load_from_data2(self):
+ self.assertEqual(self._testdata, self.loads(DATA2))
+
+ def test_load_classic_instance(self):
+ # See issue5180. Test loading 2.x pickles that
+ # contain an instance of old style class.
+ for X, args in [(C, ()), (D, ('x',)), (E, ())]:
+ xname = X.__name__.encode('ascii')
+ # Protocol 0 (text mode pickle):
+ """
+ 0: ( MARK
+ 1: i INST '__main__ X' (MARK at 0)
+ 15: p PUT 0
+ 18: ( MARK
+ 19: d DICT (MARK at 18)
+ 20: p PUT 1
+ 23: b BUILD
+ 24: . STOP
+ """
+ pickle0 = (b"(i__main__\n"
+ b"X\n"
+ b"p0\n"
+ b"(dp1\nb.").replace(b'X', xname)
+ self.assertEqual(X(*args), self.loads(pickle0))
+
+ # Protocol 1 (binary mode pickle)
+ """
+ 0: ( MARK
+ 1: c GLOBAL '__main__ X'
+ 15: q BINPUT 0
+ 17: o OBJ (MARK at 0)
+ 18: q BINPUT 1
+ 20: } EMPTY_DICT
+ 21: q BINPUT 2
+ 23: b BUILD
+ 24: . STOP
+ """
+ pickle1 = (b'(c__main__\n'
+ b'X\n'
+ b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
+ self.assertEqual(X(*args), self.loads(pickle1))
+
+ # Protocol 2 (pickle2 = b'\x80\x02' + pickle1)
+ """
+ 0: \x80 PROTO 2
+ 2: ( MARK
+ 3: c GLOBAL '__main__ X'
+ 17: q BINPUT 0
+ 19: o OBJ (MARK at 2)
+ 20: q BINPUT 1
+ 22: } EMPTY_DICT
+ 23: q BINPUT 2
+ 25: b BUILD
+ 26: . STOP
+ """
+ pickle2 = (b'\x80\x02(c__main__\n'
+ b'X\n'
+ b'q\x00oq\x01}q\x02b.').replace(b'X', xname)
+ self.assertEqual(X(*args), self.loads(pickle2))
# There are gratuitous differences between pickles produced by
# pickle and cPickle, largely because cPickle starts PUT indices at
@@ -461,11 +535,12 @@ class AbstractPickleTests(unittest.TestCase):
# is a mystery. cPickle also suppresses PUT for objects with a refcount
# of 1.
def dont_test_disassembly(self):
+ from io import StringIO
from pickletools import dis
for proto, expected in (0, DATA0_DIS), (1, DATA1_DIS):
s = self.dumps(self._testdata, proto)
- filelike = cStringIO.StringIO()
+ filelike = StringIO()
dis(s, out=filelike)
got = filelike.getvalue()
self.assertEqual(expected, got)
@@ -495,7 +570,7 @@ class AbstractPickleTests(unittest.TestCase):
for proto in protocols:
s = self.dumps(d, proto)
x = self.loads(s)
- self.assertEqual(x.keys(), [1])
+ self.assertEqual(list(x.keys()), [1])
self.assertTrue(x[1] is x)
def test_recursive_inst(self):
@@ -518,48 +593,63 @@ class AbstractPickleTests(unittest.TestCase):
x = self.loads(s)
self.assertEqual(len(x), 1)
self.assertEqual(dir(x[0]), dir(i))
- self.assertEqual(x[0].attr.keys(), [1])
+ self.assertEqual(list(x[0].attr.keys()), [1])
self.assertTrue(x[0].attr[1] is x)
- def test_garyp(self):
- self.assertRaises(self.error, self.loads, 'garyp')
+ def test_get(self):
+ self.assertRaises(KeyError, self.loads, b'g0\np0')
+ self.assertEqual(self.loads(b'((Kdtp0\nh\x00l.))'), [(100,), (100,)])
def test_insecure_strings(self):
- insecure = ["abc", "2 + 2", # not quoted
- #"'abc' + 'def'", # not a single quoted string
- "'abc", # quote is not closed
- "'abc\"", # open quote and close quote don't match
- "'abc' ?", # junk after close quote
- "'\\'", # trailing backslash
+ # XXX Some of these tests are temporarily disabled
+ insecure = [b"abc", b"2 + 2", # not quoted
+ ## b"'abc' + 'def'", # not a single quoted string
+ b"'abc", # quote is not closed
+ b"'abc\"", # open quote and close quote don't match
+ b"'abc' ?", # junk after close quote
+ b"'\\'", # trailing backslash
# some tests of the quoting rules
- #"'abc\"\''",
- #"'\\\\a\'\'\'\\\'\\\\\''",
+ ## b"'abc\"\''",
+ ## b"'\\\\a\'\'\'\\\'\\\\\''",
]
- for s in insecure:
- buf = "S" + s + "\012p0\012."
+ for b in insecure:
+ buf = b"S" + b + b"\012p0\012."
self.assertRaises(ValueError, self.loads, buf)
- if have_unicode:
- def test_unicode(self):
- endcases = [u'', u'<\\u>', u'<\\\u1234>', u'<\n>',
- u'<\\>', u'<\\\U00012345>']
- for proto in protocols:
- for u in endcases:
- p = self.dumps(u, proto)
- u2 = self.loads(p)
- self.assertEqual(u2, u)
+ def test_unicode(self):
+ endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
+ '<\\>', '<\\\U00012345>',
+ # surrogates
+ '<\udc80>']
+ for proto in protocols:
+ for u in endcases:
+ p = self.dumps(u, proto)
+ u2 = self.loads(p)
+ self.assertEqual(u2, u)
- def test_unicode_high_plane(self):
- t = u'\U00012345'
- for proto in protocols:
- p = self.dumps(t, proto)
- t2 = self.loads(p)
- self.assertEqual(t2, t)
+ def test_unicode_high_plane(self):
+ t = '\U00012345'
+ for proto in protocols:
+ p = self.dumps(t, proto)
+ t2 = self.loads(p)
+ self.assertEqual(t2, t)
+
+ def test_bytes(self):
+ for proto in protocols:
+ for s in b'', b'xyz', b'xyz'*100:
+ p = self.dumps(s)
+ self.assertEqual(self.loads(p), s)
+ for s in [bytes([i]) for i in range(256)]:
+ p = self.dumps(s)
+ self.assertEqual(self.loads(p), s)
+ for s in [bytes([i, i]) for i in range(256)]:
+ p = self.dumps(s)
+ self.assertEqual(self.loads(p), s)
def test_ints(self):
import sys
for proto in protocols:
- n = sys.maxint
+ n = sys.maxsize
while n:
for expected in (-n, n):
s = self.dumps(expected, proto)
@@ -568,20 +658,20 @@ class AbstractPickleTests(unittest.TestCase):
n = n >> 1
def test_maxint64(self):
- maxint64 = (1L << 63) - 1
- data = 'I' + str(maxint64) + '\n.'
+ maxint64 = (1 << 63) - 1
+ data = b'I' + str(maxint64).encode("ascii") + b'\n.'
got = self.loads(data)
self.assertEqual(got, maxint64)
# Try too with a bogus literal.
- data = 'I' + str(maxint64) + 'JUNK\n.'
+ data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
self.assertRaises(ValueError, self.loads, data)
def test_long(self):
for proto in protocols:
# 256 bytes is where LONG4 begins.
for nbits in 1, 8, 8*254, 8*255, 8*256, 8*257:
- nbase = 1L << nbits
+ nbase = 1 << nbits
for npos in nbase-1, nbase, nbase+1:
for n in npos, -npos:
pickle = self.dumps(n, proto)
@@ -589,7 +679,7 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(n, got)
# Try a monster. This is quadratic-time in protos 0 & 1, so don't
# bother with those.
- nbase = long("deadbeeffeedface", 16)
+ nbase = int("deadbeeffeedface", 16)
nbase += nbase << 1000000
for n in nbase, -nbase:
p = self.dumps(n, 2)
@@ -608,8 +698,8 @@ class AbstractPickleTests(unittest.TestCase):
@run_with_locale('LC_ALL', 'de_DE', 'fr_FR')
def test_float_format(self):
- # make sure that floats are formatted locale independent
- self.assertEqual(self.dumps(1.2)[0:3], 'F1.')
+ # make sure that floats are formatted locale independent with proto 0
+ self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.')
def test_reduce(self):
pass
@@ -617,6 +707,11 @@ class AbstractPickleTests(unittest.TestCase):
def test_getinitargs(self):
pass
+ def test_pop_empty_stack(self):
+ # Test issue7455
+ s = b'0'
+ self.assertRaises((pickle.UnpicklingError, IndexError), self.loads, s)
+
def test_metaclass(self):
a = use_metaclass()
for proto in protocols:
@@ -626,7 +721,7 @@ class AbstractPickleTests(unittest.TestCase):
def test_dynamic_class(self):
a = create_dynamic_class("my_dynamic_class", (object,))
- copy_reg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
+ copyreg.pickle(pickling_metaclass, pickling_metaclass.__reduce__)
for proto in protocols:
s = self.dumps(a, proto)
b = self.loads(s)
@@ -659,22 +754,22 @@ class AbstractPickleTests(unittest.TestCase):
for proto in protocols:
expected = build_none
if proto >= 2:
- expected = pickle.PROTO + chr(proto) + expected
+ expected = pickle.PROTO + bytes([proto]) + expected
p = self.dumps(None, proto)
self.assertEqual(p, expected)
oob = protocols[-1] + 1 # a future protocol
- badpickle = pickle.PROTO + chr(oob) + build_none
+ badpickle = pickle.PROTO + bytes([oob]) + build_none
try:
self.loads(badpickle)
- except ValueError, detail:
+ except ValueError as detail:
self.assertTrue(str(detail).startswith(
"unsupported pickle protocol"))
else:
self.fail("expected bad protocol number to raise ValueError")
def test_long1(self):
- x = 12345678910111213141516178920L
+ x = 12345678910111213141516178920
for proto in protocols:
s = self.dumps(x, proto)
y = self.loads(s)
@@ -682,7 +777,7 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(opcode_in_pickle(pickle.LONG1, s), proto >= 2)
def test_long4(self):
- x = 12345678910111213141516178920L << (256*8)
+ x = 12345678910111213141516178920 << (256*8)
for proto in protocols:
s = self.dumps(x, proto)
y = self.loads(s)
@@ -708,6 +803,12 @@ class AbstractPickleTests(unittest.TestCase):
(2, 2): pickle.TUPLE2,
(2, 3): pickle.TUPLE3,
(2, 4): pickle.TUPLE,
+
+ (3, 0): pickle.EMPTY_TUPLE,
+ (3, 1): pickle.TUPLE1,
+ (3, 2): pickle.TUPLE2,
+ (3, 3): pickle.TUPLE3,
+ (3, 4): pickle.TUPLE,
}
a = ()
b = (1,)
@@ -727,14 +828,17 @@ class AbstractPickleTests(unittest.TestCase):
expected_opcode = {(0, None): pickle.NONE,
(1, None): pickle.NONE,
(2, None): pickle.NONE,
+ (3, None): pickle.NONE,
(0, True): pickle.INT,
(1, True): pickle.INT,
(2, True): pickle.NEWTRUE,
+ (3, True): pickle.NEWTRUE,
(0, False): pickle.INT,
(1, False): pickle.INT,
(2, False): pickle.NEWFALSE,
+ (3, False): pickle.NEWFALSE,
}
for proto in protocols:
for x in None, False, True:
@@ -776,22 +880,22 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(B(x), B(y), detail)
self.assertEqual(x.__dict__, y.__dict__, detail)
- # Register a type with copy_reg, with extension code extcode. Pickle
+ # Register a type with copyreg, with extension code extcode. Pickle
# an object of that type. Check that the resulting pickle uses opcode
# (EXT[124]) under proto 2, and not in proto 1.
def produce_global_ext(self, extcode, opcode):
e = ExtensionSaver(extcode)
try:
- copy_reg.add_extension(__name__, "MyList", extcode)
+ copyreg.add_extension(__name__, "MyList", extcode)
x = MyList([1, 2, 3])
x.foo = 42
x.bar = "hello"
# Dump using protocol 1 for comparison.
s1 = self.dumps(x, 1)
- self.assertIn(__name__, s1)
- self.assertIn("MyList", s1)
+ self.assertIn(__name__.encode("utf-8"), s1)
+ self.assertIn(b"MyList", s1)
self.assertEqual(opcode_in_pickle(opcode, s1), False)
y = self.loads(s1)
@@ -800,9 +904,9 @@ class AbstractPickleTests(unittest.TestCase):
# Dump using protocol 2 for test.
s2 = self.dumps(x, 2)
- self.assertNotIn(__name__, s2)
- self.assertNotIn("MyList", s2)
- self.assertEqual(opcode_in_pickle(opcode, s2), True)
+ self.assertNotIn(__name__.encode("utf-8"), s2)
+ self.assertNotIn(b"MyList", s2)
+ self.assertEqual(opcode_in_pickle(opcode, s2), True, repr(s2))
y = self.loads(s2)
self.assertEqual(list(x), list(y))
@@ -827,7 +931,7 @@ class AbstractPickleTests(unittest.TestCase):
def test_list_chunking(self):
n = 10 # too small to chunk
- x = range(n)
+ x = list(range(n))
for proto in protocols:
s = self.dumps(x, proto)
y = self.loads(s)
@@ -836,7 +940,7 @@ class AbstractPickleTests(unittest.TestCase):
self.assertEqual(num_appends, proto > 0)
n = 2500 # expect at least two chunks when proto > 0
- x = range(n)
+ x = list(range(n))
for proto in protocols:
s = self.dumps(x, proto)
y = self.loads(s)
@@ -852,6 +956,7 @@ class AbstractPickleTests(unittest.TestCase):
x = dict.fromkeys(range(n))
for proto in protocols:
s = self.dumps(x, proto)
+ self.assertIsInstance(s, bytes_types)
y = self.loads(s)
self.assertEqual(x, y)
num_setitems = count_opcode(pickle.SETITEMS, s)
@@ -935,6 +1040,14 @@ class AbstractPickleTests(unittest.TestCase):
y = self.loads(s)
self.assertEqual(y._reduce_called, 1)
+ def test_bad_getattr(self):
+ x = BadGetattr()
+ for proto in 0, 1:
+ self.assertRaises(RuntimeError, self.dumps, x, proto)
+ # protocol 2 don't raise a RuntimeError.
+ d = self.dumps(x, 2)
+ self.assertRaises(RuntimeError, self.loads, d)
+
def test_reduce_bad_iterator(self):
# Issue4176: crash when 4th and 5th items of __reduce__()
# are not iterators
@@ -951,17 +1064,17 @@ class AbstractPickleTests(unittest.TestCase):
for proto in protocols:
try:
self.dumps(C(), proto)
- except (AttributeError, pickle.PickleError, cPickle.PickleError):
+ except (pickle.PickleError):
pass
try:
self.dumps(D(), proto)
- except (AttributeError, pickle.PickleError, cPickle.PickleError):
+ except (pickle.PickleError):
pass
def test_many_puts_and_gets(self):
# Test that internal data structures correctly deal with lots of
# puts/gets.
- keys = ("aaa" + str(i) for i in xrange(100))
+ keys = ("aaa" + str(i) for i in range(100))
large_dict = dict((k, [4, 5, 6]) for k in keys)
obj = [dict(large_dict), dict(large_dict), dict(large_dict)]
@@ -986,6 +1099,153 @@ class AbstractPickleTests(unittest.TestCase):
for x_key, y_key in zip(x_keys, y_keys):
self.assertIs(x_key, y_key)
+ def test_unpickle_from_2x(self):
+ # Unpickle non-trivial data from Python 2.x.
+ loaded = self.loads(DATA3)
+ self.assertEqual(loaded, set([1, 2]))
+ loaded = self.loads(DATA4)
+ self.assertEqual(type(loaded), type(range(0)))
+ self.assertEqual(list(loaded), list(range(5)))
+ loaded = self.loads(DATA5)
+ self.assertEqual(type(loaded), SimpleCookie)
+ self.assertEqual(list(loaded.keys()), ["key"])
+ self.assertEqual(loaded["key"].value, "Set-Cookie: key=value")
+
+ def test_pickle_to_2x(self):
+ # Pickle non-trivial data with protocol 2, expecting that it yields
+ # the same result as Python 2.x did.
+ # NOTE: this test is a bit too strong since we can produce different
+ # bytecode that 2.x will still understand.
+ dumped = self.dumps(range(5), 2)
+ self.assertEqual(dumped, DATA4)
+ dumped = self.dumps(set([3]), 2)
+ self.assertEqual(dumped, DATA6)
+
+ def test_large_pickles(self):
+ # Test the correctness of internal buffering routines when handling
+ # large data.
+ for proto in protocols:
+ data = (1, min, b'xy' * (30 * 1024), len)
+ dumped = self.dumps(data, proto)
+ loaded = self.loads(dumped)
+ self.assertEqual(len(loaded), len(data))
+ self.assertEqual(loaded, data)
+
+ def test_empty_bytestring(self):
+ # issue 11286
+ empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
+ self.assertEqual(empty, '')
+
+ def check_negative_32b_binXXX(self, dumped):
+ if sys.maxsize > 2**32:
+ self.skipTest("test is only meaningful on 32-bit builds")
+ # XXX Pure Python pickle reads lengths as signed and passes
+ # them directly to read() (hence the EOFError)
+ with self.assertRaises((pickle.UnpicklingError, EOFError,
+ ValueError, OverflowError)):
+ self.loads(dumped)
+
+ def test_negative_32b_binbytes(self):
+ # On 32-bit builds, a BINBYTES of 2**31 or more is refused
+ self.check_negative_32b_binXXX(b'\x80\x03B\xff\xff\xff\xffxyzq\x00.')
+
+ def test_negative_32b_binunicode(self):
+ # On 32-bit builds, a BINUNICODE of 2**31 or more is refused
+ self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.')
+
+ def test_negative_put(self):
+ # Issue #12847
+ dumped = b'Va\np-1\n.'
+ self.assertRaises(ValueError, self.loads, dumped)
+
+ def test_negative_32b_binput(self):
+ # Issue #12847
+ if sys.maxsize > 2**32:
+ self.skipTest("test is only meaningful on 32-bit builds")
+ dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
+ self.assertRaises(ValueError, self.loads, dumped)
+
+
+class BigmemPickleTests(unittest.TestCase):
+
+ # Binary protocols can serialize longs of up to 2GB-1
+
+ @bigmemtest(size=_2G, memuse=1 + 1, dry_run=False)
+ def test_huge_long_32b(self, size):
+ data = 1 << (8 * size)
+ try:
+ for proto in protocols:
+ if proto < 2:
+ continue
+ with self.assertRaises((ValueError, OverflowError)):
+ self.dumps(data, protocol=proto)
+ finally:
+ data = None
+
+ # Protocol 3 can serialize up to 4GB-1 as a bytes object
+ # (older protocols don't have a dedicated opcode for bytes and are
+ # too inefficient)
+
+ @bigmemtest(size=_2G, memuse=1 + 1, dry_run=False)
+ def test_huge_bytes_32b(self, size):
+ data = b"abcd" * (size // 4)
+ try:
+ for proto in protocols:
+ if proto < 3:
+ continue
+ try:
+ pickled = self.dumps(data, protocol=proto)
+ self.assertTrue(b"abcd" in pickled[:15])
+ self.assertTrue(b"abcd" in pickled[-15:])
+ finally:
+ pickled = None
+ finally:
+ data = None
+
+ @bigmemtest(size=_4G, memuse=1 + 1, dry_run=False)
+ def test_huge_bytes_64b(self, size):
+ data = b"a" * size
+ try:
+ for proto in protocols:
+ if proto < 3:
+ continue
+ with self.assertRaises((ValueError, OverflowError)):
+ self.dumps(data, protocol=proto)
+ finally:
+ data = None
+
+ # All protocols use 1-byte per printable ASCII character; we add another
+ # byte because the encoded form has to be copied into the internal buffer.
+
+ @bigmemtest(size=_2G, memuse=2 + character_size, dry_run=False)
+ def test_huge_str_32b(self, size):
+ data = "abcd" * (size // 4)
+ try:
+ for proto in protocols:
+ try:
+ pickled = self.dumps(data, protocol=proto)
+ self.assertTrue(b"abcd" in pickled[:15])
+ self.assertTrue(b"abcd" in pickled[-15:])
+ finally:
+ pickled = None
+ finally:
+ data = None
+
+ # BINUNICODE (protocols 1, 2 and 3) cannot carry more than
+ # 2**32 - 1 bytes of utf-8 encoded unicode.
+
+ @bigmemtest(size=_4G, memuse=1 + character_size, dry_run=False)
+ def test_huge_str_64b(self, size):
+ data = "a" * size
+ try:
+ for proto in protocols:
+ if proto == 0:
+ continue
+ with self.assertRaises((ValueError, OverflowError)):
+ self.dumps(data, protocol=proto)
+ finally:
+ data = None
+
# Test classes for reduce_ex
@@ -1009,7 +1269,7 @@ class REX_three(object):
self._proto = proto
return REX_two, ()
def __reduce__(self):
- raise TestFailed, "This __reduce__ shouldn't be called"
+ raise TestFailed("This __reduce__ shouldn't be called")
class REX_four(object):
_proto = None
@@ -1030,9 +1290,6 @@ class REX_five(object):
class MyInt(int):
sample = 1
-class MyLong(long):
- sample = 1L
-
class MyFloat(float):
sample = 1.0
@@ -1042,8 +1299,8 @@ class MyComplex(complex):
class MyStr(str):
sample = "hello"
-class MyUnicode(unicode):
- sample = u"hello \u1234"
+class MyUnicode(str):
+ sample = "hello \u1234"
class MyTuple(tuple):
sample = (1, 2, 3)
@@ -1054,7 +1311,7 @@ class MyList(list):
class MyDict(dict):
sample = {"a": 1, "b": 2}
-myclasses = [MyInt, MyLong, MyFloat,
+myclasses = [MyInt, MyFloat,
MyComplex,
MyStr, MyUnicode,
MyTuple, MyList, MyDict]
@@ -1068,70 +1325,70 @@ class SimpleNewObj(object):
# raise an error, to make sure this isn't called
raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
+class BadGetattr:
+ def __getattr__(self, key):
+ self.foo
+
+
class AbstractPickleModuleTests(unittest.TestCase):
def test_dump_closed_file(self):
import os
- f = open(TESTFN, "w")
+ f = open(TESTFN, "wb")
try:
f.close()
- self.assertRaises(ValueError, self.module.dump, 123, f)
+ self.assertRaises(ValueError, pickle.dump, 123, f)
finally:
os.remove(TESTFN)
def test_load_closed_file(self):
import os
- f = open(TESTFN, "w")
+ f = open(TESTFN, "wb")
try:
f.close()
- self.assertRaises(ValueError, self.module.dump, 123, f)
+ self.assertRaises(ValueError, pickle.dump, 123, f)
finally:
os.remove(TESTFN)
def test_load_from_and_dump_to_file(self):
- stream = cStringIO.StringIO()
+ stream = io.BytesIO()
data = [123, {}, 124]
- self.module.dump(data, stream)
+ pickle.dump(data, stream)
stream.seek(0)
- unpickled = self.module.load(stream)
+ unpickled = pickle.load(stream)
self.assertEqual(unpickled, data)
def test_highest_protocol(self):
# Of course this needs to be changed when HIGHEST_PROTOCOL changes.
- self.assertEqual(self.module.HIGHEST_PROTOCOL, 2)
+ self.assertEqual(pickle.HIGHEST_PROTOCOL, 3)
def test_callapi(self):
- f = cStringIO.StringIO()
+ f = io.BytesIO()
# With and without keyword arguments
- self.module.dump(123, f, -1)
- self.module.dump(123, file=f, protocol=-1)
- self.module.dumps(123, -1)
- self.module.dumps(123, protocol=-1)
- self.module.Pickler(f, -1)
- self.module.Pickler(f, protocol=-1)
-
- def test_incomplete_input(self):
- s = StringIO.StringIO("X''.")
- self.assertRaises(EOFError, self.module.load, s)
-
- def test_restricted(self):
- # issue7128: cPickle failed in restricted mode
- builtins = {self.module.__name__: self.module,
- '__import__': __import__}
- d = {}
- teststr = "def f(): {0}.dumps(0)".format(self.module.__name__)
- exec teststr in {'__builtins__': builtins}, d
- d['f']()
+ pickle.dump(123, f, -1)
+ pickle.dump(123, file=f, protocol=-1)
+ pickle.dumps(123, -1)
+ pickle.dumps(123, protocol=-1)
+ pickle.Pickler(f, -1)
+ pickle.Pickler(f, protocol=-1)
+
+ def test_bad_init(self):
+ # Test issue3664 (pickle can segfault from a badly initialized Pickler).
+ # Override initialization without calling __init__() of the superclass.
+ class BadPickler(pickle.Pickler):
+ def __init__(self): pass
+
+ class BadUnpickler(pickle.Unpickler):
+ def __init__(self): pass
+
+ self.assertRaises(pickle.PicklingError, BadPickler().dump, 0)
+ self.assertRaises(pickle.UnpicklingError, BadUnpickler().load)
def test_bad_input(self):
# Test issue4298
- s = '\x58\0\0\0\x54'
- self.assertRaises(EOFError, self.module.loads, s)
- # Test issue7455
- s = '0'
- # XXX Why doesn't pickle raise UnpicklingError?
- self.assertRaises((IndexError, cPickle.UnpicklingError),
- self.module.loads, s)
+ s = bytes([0x58, 0, 0, 0, 0x54])
+ self.assertRaises(EOFError, pickle.loads, s)
+
class AbstractPersistentPicklerTests(unittest.TestCase):
@@ -1155,7 +1412,7 @@ class AbstractPersistentPicklerTests(unittest.TestCase):
def test_persistence(self):
self.id_count = 0
self.load_count = 0
- L = range(10)
+ L = list(range(10))
self.assertEqual(self.loads(self.dumps(L)), L)
self.assertEqual(self.id_count, 5)
self.assertEqual(self.load_count, 5)
@@ -1163,11 +1420,12 @@ class AbstractPersistentPicklerTests(unittest.TestCase):
def test_bin_persistence(self):
self.id_count = 0
self.load_count = 0
- L = range(10)
+ L = list(range(10))
self.assertEqual(self.loads(self.dumps(L, 1)), L)
self.assertEqual(self.id_count, 5)
self.assertEqual(self.load_count, 5)
+
class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
pickler_class = None
@@ -1184,7 +1442,7 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
# object again, the third serialized form should be identical to the
# first one we obtained.
data = ["abcdefg", "abcdefg", 44]
- f = cStringIO.StringIO()
+ f = io.BytesIO()
pickler = self.pickler_class(f)
pickler.dump(data)
@@ -1211,13 +1469,13 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
def test_priming_pickler_memo(self):
# Verify that we can set the Pickler's memo attribute.
data = ["abcdefg", "abcdefg", 44]
- f = cStringIO.StringIO()
+ f = io.BytesIO()
pickler = self.pickler_class(f)
pickler.dump(data)
first_pickled = f.getvalue()
- f = cStringIO.StringIO()
+ f = io.BytesIO()
primed = self.pickler_class(f)
primed.memo = pickler.memo
@@ -1229,25 +1487,25 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
def test_priming_unpickler_memo(self):
# Verify that we can set the Unpickler's memo attribute.
data = ["abcdefg", "abcdefg", 44]
- f = cStringIO.StringIO()
+ f = io.BytesIO()
pickler = self.pickler_class(f)
pickler.dump(data)
first_pickled = f.getvalue()
- f = cStringIO.StringIO()
+ f = io.BytesIO()
primed = self.pickler_class(f)
primed.memo = pickler.memo
primed.dump(data)
primed_pickled = f.getvalue()
- unpickler = self.unpickler_class(cStringIO.StringIO(first_pickled))
+ unpickler = self.unpickler_class(io.BytesIO(first_pickled))
unpickled_data1 = unpickler.load()
self.assertEqual(unpickled_data1, data)
- primed = self.unpickler_class(cStringIO.StringIO(primed_pickled))
+ primed = self.unpickler_class(io.BytesIO(primed_pickled))
primed.memo = unpickler.memo
unpickled_data2 = primed.load()
@@ -1258,18 +1516,18 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
def test_reusing_unpickler_objects(self):
data1 = ["abcdefg", "abcdefg", 44]
- f = cStringIO.StringIO()
+ f = io.BytesIO()
pickler = self.pickler_class(f)
pickler.dump(data1)
pickled1 = f.getvalue()
data2 = ["abcdefg", 44, 44]
- f = cStringIO.StringIO()
+ f = io.BytesIO()
pickler = self.pickler_class(f)
pickler.dump(data2)
pickled2 = f.getvalue()
- f = cStringIO.StringIO()
+ f = io.BytesIO()
f.write(pickled1)
f.seek(0)
unpickler = self.unpickler_class(f)
@@ -1280,3 +1538,60 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
f.write(pickled2)
f.seek(0)
self.assertEqual(unpickler.load(), data2)
+
+ def _check_multiple_unpicklings(self, ioclass):
+ for proto in protocols:
+ data1 = [(x, str(x)) for x in range(2000)] + [b"abcde", len]
+ f = ioclass()
+ pickler = self.pickler_class(f, protocol=proto)
+ pickler.dump(data1)
+ pickled = f.getvalue()
+
+ N = 5
+ f = ioclass(pickled * N)
+ unpickler = self.unpickler_class(f)
+ for i in range(N):
+ if f.seekable():
+ pos = f.tell()
+ self.assertEqual(unpickler.load(), data1)
+ if f.seekable():
+ self.assertEqual(f.tell(), pos + len(pickled))
+ self.assertRaises(EOFError, unpickler.load)
+
+ def test_multiple_unpicklings_seekable(self):
+ self._check_multiple_unpicklings(io.BytesIO)
+
+ def test_multiple_unpicklings_unseekable(self):
+ self._check_multiple_unpicklings(UnseekableIO)
+
+ def test_unpickling_buffering_readline(self):
+ # Issue #12687: the unpickler's buffering logic could fail with
+ # text mode opcodes.
+ data = list(range(10))
+ for proto in protocols:
+ for buf_size in range(1, 11):
+ f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
+ pickler = self.pickler_class(f, protocol=proto)
+ pickler.dump(data)
+ f.seek(0)
+ unpickler = self.unpickler_class(f)
+ self.assertEqual(unpickler.load(), data)
+
+
+if __name__ == "__main__":
+ # Print some stuff that can be used to rewrite DATA{0,1,2}
+ from pickletools import dis
+ x = create_data()
+ for i in range(3):
+ p = pickle.dumps(x, i)
+ print("DATA{0} = (".format(i))
+ for j in range(0, len(p), 20):
+ b = bytes(p[j:j+20])
+ print(" {0!r}".format(b))
+ print(")")
+ print()
+ print("# Disassembly of DATA{0}".format(i))
+ print("DATA{0}_DIS = \"\"\"\\".format(i))
+ dis(p)
+ print("\"\"\"")
+ print()