1
+ import io
1
2
import pickle
2
3
import pickletools
3
4
import sys
@@ -11,13 +12,73 @@ def test_module_dir():
11
12
assert dir (cPickle ) == ['Custom' , '__doc__' , '__file__' , '__loader__' , '__name__' , '__package__' , '__spec__' ]
12
13
13
14
15
+ ARGS_FOR_CUSTOM_CLASS = ('FIRST' , 'LAST' , 11 )
16
+ PICKLE_BYTES_FOR_CUSTOM_CLASS = (b'\x80 \x04 \x95 f\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x8c \x12 cPyExtPatt.cPickle\x94 '
17
+ b'\x8c \x06 Custom\x94 \x93 \x94 )\x81 \x94 }\x94 (\x8c \x05 first\x94 \x8c \x05 FIRST'
18
+ b'\x94 \x8c \x04 last\x94 \x8c \x04 LAST\x94 \x8c \x06 number\x94 K\x0b \x8c \x0f _pickle_'
19
+ b'version\x94 K\x01 ub.' )
20
+
21
+
14
22
def test_pickle_getstate ():
15
- custom = cPickle .Custom ('FIRST' , 'LAST' , 11 )
23
+ custom = cPickle .Custom (* ARGS_FOR_CUSTOM_CLASS )
16
24
pickled_value = pickle .dumps (custom )
17
25
print ()
18
26
print (f'Pickled original is { pickled_value } ' )
19
- assert pickled_value == (b'\x80 \x04 \x95 f\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x8c \x12 cPyExtPatt.cPickle\x94 '
20
- b'\x8c \x06 Custom\x94 \x93 \x94 )\x81 \x94 }\x94 (\x8c \x05 first\x94 \x8c \x05 FIRST'
21
- b'\x94 \x8c \x04 last\x94 \x8c \x04 LAST\x94 \x8c \x06 number\x94 K\x0b \x8c \x0f _pickle_'
22
- b'version\x94 K\x01 ub.' )
27
+ assert pickled_value == PICKLE_BYTES_FOR_CUSTOM_CLASS
23
28
# result = pickle.loads(pickled_value)
29
+
30
+
31
+ def test_pickle_setstate ():
32
+ custom = pickle .loads (PICKLE_BYTES_FOR_CUSTOM_CLASS )
33
+ assert custom .first == 'FIRST'
34
+ assert custom .last == 'LAST'
35
+ assert custom .number == 11
36
+
37
+
38
+ def test_pickle_round_trip ():
39
+ custom = cPickle .Custom (* ARGS_FOR_CUSTOM_CLASS )
40
+ pickled_value = pickle .dumps (custom )
41
+ result = pickle .loads (pickled_value )
42
+ assert id (result ) != id (custom )
43
+
44
+
45
+ def test_pickletools ():
46
+ outfile = io .StringIO ()
47
+ pickletools .dis (PICKLE_BYTES_FOR_CUSTOM_CLASS , out = outfile , annotate = 1 )
48
+ result = outfile .getvalue ()
49
+ # print()
50
+ # print(result)
51
+ expected = """ 0: \\ x80 PROTO 4 Protocol version indicator.
52
+ 2: \\ x95 FRAME 102 Indicate the beginning of a new frame.
53
+ 11: \\ x8c SHORT_BINUNICODE 'cPyExtPatt.cPickle' Push a Python Unicode string object.
54
+ 31: \\ x94 MEMOIZE (as 0) Store the stack top into the memo. The stack is not popped.
55
+ 32: \\ x8c SHORT_BINUNICODE 'Custom' Push a Python Unicode string object.
56
+ 40: \\ x94 MEMOIZE (as 1) Store the stack top into the memo. The stack is not popped.
57
+ 41: \\ x93 STACK_GLOBAL Push a global object (module.attr) on the stack.
58
+ 42: \\ x94 MEMOIZE (as 2) Store the stack top into the memo. The stack is not popped.
59
+ 43: ) EMPTY_TUPLE Push an empty tuple.
60
+ 44: \\ x81 NEWOBJ Build an object instance.
61
+ 45: \\ x94 MEMOIZE (as 3) Store the stack top into the memo. The stack is not popped.
62
+ 46: } EMPTY_DICT Push an empty dict.
63
+ 47: \\ x94 MEMOIZE (as 4) Store the stack top into the memo. The stack is not popped.
64
+ 48: ( MARK Push markobject onto the stack.
65
+ 49: \\ x8c SHORT_BINUNICODE 'first' Push a Python Unicode string object.
66
+ 56: \\ x94 MEMOIZE (as 5) Store the stack top into the memo. The stack is not popped.
67
+ 57: \\ x8c SHORT_BINUNICODE 'FIRST' Push a Python Unicode string object.
68
+ 64: \\ x94 MEMOIZE (as 6) Store the stack top into the memo. The stack is not popped.
69
+ 65: \\ x8c SHORT_BINUNICODE 'last' Push a Python Unicode string object.
70
+ 71: \\ x94 MEMOIZE (as 7) Store the stack top into the memo. The stack is not popped.
71
+ 72: \\ x8c SHORT_BINUNICODE 'LAST' Push a Python Unicode string object.
72
+ 78: \\ x94 MEMOIZE (as 8) Store the stack top into the memo. The stack is not popped.
73
+ 79: \\ x8c SHORT_BINUNICODE 'number' Push a Python Unicode string object.
74
+ 87: \\ x94 MEMOIZE (as 9) Store the stack top into the memo. The stack is not popped.
75
+ 88: K BININT1 11 Push a one-byte unsigned integer.
76
+ 90: \\ x8c SHORT_BINUNICODE '_pickle_version' Push a Python Unicode string object.
77
+ 107: \\ x94 MEMOIZE (as 10) Store the stack top into the memo. The stack is not popped.
78
+ 108: K BININT1 1 Push a one-byte unsigned integer.
79
+ 110: u SETITEMS (MARK at 48) Add an arbitrary number of key+value pairs to an existing dict.
80
+ 111: b BUILD Finish building an object, via __setstate__ or dict update.
81
+ 112: . STOP Stop the unpickling machine.
82
+ highest protocol among opcodes = 4
83
+ """
84
+ assert result == expected
0 commit comments