summaryrefslogtreecommitdiffstats
path: root/Lib/pickletools.py
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-01-28 15:27:57 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-01-28 15:27:57 (GMT)
commitd0f7c86a20e9cef8cbf2c8fb676fcc8d8a7000b4 (patch)
treedbb687921cbbff2baf04022d02361e2a153eaa69 /Lib/pickletools.py
parent1be31759929c67a3f0b8d11ac8a48ab881760fa8 (diff)
downloadcpython-d0f7c86a20e9cef8cbf2c8fb676fcc8d8a7000b4.zip
cpython-d0f7c86a20e9cef8cbf2c8fb676fcc8d8a7000b4.tar.gz
cpython-d0f7c86a20e9cef8cbf2c8fb676fcc8d8a7000b4.tar.bz2
dis(): Not all opcodes are printable anymore, so print the repr
of the opcode character instead (but stripping the quotes). Added a proto 2 test section for the canonical recursive-tuple case. Note that since pickle's save_tuple() takes different paths depending on tuple length now, beefier tests are really needed (but not in pickletools); the "short tuple" case tried here was actually broken yesterday, and it's subtle stuff so needs to be tested.
Diffstat (limited to 'Lib/pickletools.py')
-rw-r--r--Lib/pickletools.py276
1 files changed, 150 insertions, 126 deletions
diff --git a/Lib/pickletools.py b/Lib/pickletools.py
index 11afbd0..fabeb65 100644
--- a/Lib/pickletools.py
+++ b/Lib/pickletools.py
@@ -1874,9 +1874,9 @@ def dis(pickle, out=None, indentlevel=4):
if pos is not None:
print >> out, "%5d:" % pos,
- line = "%s %s%s" % (opcode.code,
- indentchunk * len(markstack),
- opcode.name)
+ line = "%-4s %s%s" % (repr(opcode.code)[1:-1],
+ indentchunk * len(markstack),
+ opcode.name)
markmsg = None
if markstack and markobject in opcode.stack_before:
@@ -1904,103 +1904,103 @@ _dis_test = """
>>> x = [1, 2, (3, 4), {'abc': u"def"}]
>>> pkl = pickle.dumps(x, 0)
>>> dis(pkl)
- 0: ( MARK
- 1: l LIST (MARK at 0)
- 2: p PUT 0
- 5: I INT 1
- 8: a APPEND
- 9: I INT 2
- 12: a APPEND
- 13: ( MARK
- 14: I INT 3
- 17: I INT 4
- 20: t TUPLE (MARK at 13)
- 21: p PUT 1
- 24: a APPEND
- 25: ( MARK
- 26: d DICT (MARK at 25)
- 27: p PUT 2
- 30: S STRING 'abc'
- 37: p PUT 3
- 40: V UNICODE u'def'
- 45: p PUT 4
- 48: s SETITEM
- 49: a APPEND
- 50: . STOP
+ 0: ( MARK
+ 1: l LIST (MARK at 0)
+ 2: p PUT 0
+ 5: I INT 1
+ 8: a APPEND
+ 9: I INT 2
+ 12: a APPEND
+ 13: ( MARK
+ 14: I INT 3
+ 17: I INT 4
+ 20: t TUPLE (MARK at 13)
+ 21: p PUT 1
+ 24: a APPEND
+ 25: ( MARK
+ 26: d DICT (MARK at 25)
+ 27: p PUT 2
+ 30: S STRING 'abc'
+ 37: p PUT 3
+ 40: V UNICODE u'def'
+ 45: p PUT 4
+ 48: s SETITEM
+ 49: a APPEND
+ 50: . STOP
Try again with a "binary" pickle.
>>> pkl = pickle.dumps(x, 1)
>>> dis(pkl)
- 0: ] EMPTY_LIST
- 1: q BINPUT 0
- 3: ( MARK
- 4: K BININT1 1
- 6: K BININT1 2
- 8: ( MARK
- 9: K BININT1 3
- 11: K BININT1 4
- 13: t TUPLE (MARK at 8)
- 14: q BINPUT 1
- 16: } EMPTY_DICT
- 17: q BINPUT 2
- 19: U SHORT_BINSTRING 'abc'
- 24: q BINPUT 3
- 26: X BINUNICODE u'def'
- 34: q BINPUT 4
- 36: s SETITEM
- 37: e APPENDS (MARK at 3)
- 38: . STOP
+ 0: ] EMPTY_LIST
+ 1: q BINPUT 0
+ 3: ( MARK
+ 4: K BININT1 1
+ 6: K BININT1 2
+ 8: ( MARK
+ 9: K BININT1 3
+ 11: K BININT1 4
+ 13: t TUPLE (MARK at 8)
+ 14: q BINPUT 1
+ 16: } EMPTY_DICT
+ 17: q BINPUT 2
+ 19: U SHORT_BINSTRING 'abc'
+ 24: q BINPUT 3
+ 26: X BINUNICODE u'def'
+ 34: q BINPUT 4
+ 36: s SETITEM
+ 37: e APPENDS (MARK at 3)
+ 38: . STOP
Exercise the INST/OBJ/BUILD family.
>>> import random
>>> dis(pickle.dumps(random.random, 0))
- 0: c GLOBAL 'random random'
- 15: p PUT 0
- 18: . STOP
+ 0: c GLOBAL 'random random'
+ 15: p PUT 0
+ 18: . STOP
>>> x = [pickle.PicklingError()] * 2
>>> dis(pickle.dumps(x, 0))
- 0: ( MARK
- 1: l LIST (MARK at 0)
- 2: p PUT 0
- 5: ( MARK
- 6: i INST 'pickle PicklingError' (MARK at 5)
- 28: p PUT 1
- 31: ( MARK
- 32: d DICT (MARK at 31)
- 33: p PUT 2
- 36: S STRING 'args'
- 44: p PUT 3
- 47: ( MARK
- 48: t TUPLE (MARK at 47)
- 49: s SETITEM
- 50: b BUILD
- 51: a APPEND
- 52: g GET 1
- 55: a APPEND
- 56: . STOP
+ 0: ( MARK
+ 1: l LIST (MARK at 0)
+ 2: p PUT 0
+ 5: ( MARK
+ 6: i INST 'pickle PicklingError' (MARK at 5)
+ 28: p PUT 1
+ 31: ( MARK
+ 32: d DICT (MARK at 31)
+ 33: p PUT 2
+ 36: S STRING 'args'
+ 44: p PUT 3
+ 47: ( MARK
+ 48: t TUPLE (MARK at 47)
+ 49: s SETITEM
+ 50: b BUILD
+ 51: a APPEND
+ 52: g GET 1
+ 55: a APPEND
+ 56: . STOP
>>> dis(pickle.dumps(x, 1))
- 0: ] EMPTY_LIST
- 1: q BINPUT 0
- 3: ( MARK
- 4: ( MARK
- 5: c GLOBAL 'pickle PicklingError'
- 27: q BINPUT 1
- 29: o OBJ (MARK at 4)
- 30: q BINPUT 2
- 32: } EMPTY_DICT
- 33: q BINPUT 3
- 35: U SHORT_BINSTRING 'args'
- 41: q BINPUT 4
- 43: ) EMPTY_TUPLE
- 44: s SETITEM
- 45: b BUILD
- 46: h BINGET 2
- 48: e APPENDS (MARK at 3)
- 49: . STOP
+ 0: ] EMPTY_LIST
+ 1: q BINPUT 0
+ 3: ( MARK
+ 4: ( MARK
+ 5: c GLOBAL 'pickle PicklingError'
+ 27: q BINPUT 1
+ 29: o OBJ (MARK at 4)
+ 30: q BINPUT 2
+ 32: } EMPTY_DICT
+ 33: q BINPUT 3
+ 35: U SHORT_BINSTRING 'args'
+ 41: q BINPUT 4
+ 43: ) EMPTY_TUPLE
+ 44: s SETITEM
+ 45: b BUILD
+ 46: h BINGET 2
+ 48: e APPENDS (MARK at 3)
+ 49: . STOP
Try "the canonical" recursive-object test.
@@ -2016,24 +2016,24 @@ True
>>> T[0][0] is T
True
>>> dis(pickle.dumps(L, 0))
- 0: ( MARK
- 1: l LIST (MARK at 0)
- 2: p PUT 0
- 5: ( MARK
- 6: g GET 0
- 9: t TUPLE (MARK at 5)
- 10: p PUT 1
- 13: a APPEND
- 14: . STOP
+ 0: ( MARK
+ 1: l LIST (MARK at 0)
+ 2: p PUT 0
+ 5: ( MARK
+ 6: g GET 0
+ 9: t TUPLE (MARK at 5)
+ 10: p PUT 1
+ 13: a APPEND
+ 14: . STOP
>>> dis(pickle.dumps(L, 1))
- 0: ] EMPTY_LIST
- 1: q BINPUT 0
- 3: ( MARK
- 4: h BINGET 0
- 6: t TUPLE (MARK at 3)
- 7: q BINPUT 1
- 9: a APPEND
- 10: . STOP
+ 0: ] EMPTY_LIST
+ 1: q BINPUT 0
+ 3: ( MARK
+ 4: h BINGET 0
+ 6: t TUPLE (MARK at 3)
+ 7: q BINPUT 1
+ 9: a APPEND
+ 10: . STOP
The protocol 0 pickle of the tuple causes the disassembly to get confused,
as it doesn't realize that the POP opcode at 16 gets rid of the MARK at 0
@@ -2043,31 +2043,55 @@ POP_MARK gets rid of the MARK. Doing a better job on the protocol 0
pickle would require the disassembler to emulate the stack.
>>> dis(pickle.dumps(T, 0))
- 0: ( MARK
- 1: ( MARK
- 2: l LIST (MARK at 1)
- 3: p PUT 0
- 6: ( MARK
- 7: g GET 0
- 10: t TUPLE (MARK at 6)
- 11: p PUT 1
- 14: a APPEND
- 15: 0 POP
- 16: 0 POP
- 17: g GET 1
- 20: . STOP
+ 0: ( MARK
+ 1: ( MARK
+ 2: l LIST (MARK at 1)
+ 3: p PUT 0
+ 6: ( MARK
+ 7: g GET 0
+ 10: t TUPLE (MARK at 6)
+ 11: p PUT 1
+ 14: a APPEND
+ 15: 0 POP
+ 16: 0 POP
+ 17: g GET 1
+ 20: . STOP
>>> dis(pickle.dumps(T, 1))
- 0: ( MARK
- 1: ] EMPTY_LIST
- 2: q BINPUT 0
- 4: ( MARK
- 5: h BINGET 0
- 7: t TUPLE (MARK at 4)
- 8: q BINPUT 1
- 10: a APPEND
- 11: 1 POP_MARK (MARK at 0)
- 12: h BINGET 1
- 14: . STOP
+ 0: ( MARK
+ 1: ] EMPTY_LIST
+ 2: q BINPUT 0
+ 4: ( MARK
+ 5: h BINGET 0
+ 7: t TUPLE (MARK at 4)
+ 8: q BINPUT 1
+ 10: a APPEND
+ 11: 1 POP_MARK (MARK at 0)
+ 12: h BINGET 1
+ 14: . STOP
+
+Try protocol 2.
+
+>>> dis(pickle.dumps(L, 2))
+ 0: \x80 PROTO 2
+ 2: ] EMPTY_LIST
+ 3: q BINPUT 0
+ 5: h BINGET 0
+ 7: \x85 TUPLE1
+ 8: q BINPUT 1
+ 10: a APPEND
+ 11: . STOP
+
+>>> dis(pickle.dumps(T, 2))
+ 0: \x80 PROTO 2
+ 2: ] EMPTY_LIST
+ 3: q BINPUT 0
+ 5: h BINGET 0
+ 7: \x85 TUPLE1
+ 8: q BINPUT 1
+ 10: a APPEND
+ 11: 0 POP
+ 12: h BINGET 1
+ 14: . STOP
"""
__test__ = {'disassembler_test': _dis_test,