Skip to content

Commit 62235e7

Browse files
committed
dis(): Added an optional memo argument, so that multiple pickles in a
file can be dumped without (bogus) complaint if the the pickles were created using a single pickle memo.
1 parent 18e7083 commit 62235e7

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

Lib/pickletools.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,7 +1861,7 @@ def genops(pickle):
18611861
##############################################################################
18621862
# A symbolic pickle disassembler.
18631863

1864-
def dis(pickle, out=None, indentlevel=4):
1864+
def dis(pickle, out=None, memo=None, indentlevel=4):
18651865
"""Produce a symbolic disassembly of a pickle.
18661866
18671867
'pickle' is a file-like object, or string, containing a (at least one)
@@ -1871,6 +1871,12 @@ def dis(pickle, out=None, indentlevel=4):
18711871
Optional arg 'out' is a file-like object to which the disassembly is
18721872
printed. It defaults to sys.stdout.
18731873
1874+
Optional arg 'memo' is a Python dict, used as the pickle's memo. It
1875+
may be mutated by dis(), if the pickle contains PUT or BINPUT opcodes.
1876+
Passing the same memo object to another dis() call then allows disassembly
1877+
to proceed across multiple pickles that were all created by the same
1878+
pickler with the same memo. Ordinarily you don't need to worry about this.
1879+
18741880
Optional arg indentlevel is the number of blanks by which to indent
18751881
a new MARK level. It defaults to 4.
18761882
@@ -1895,7 +1901,8 @@ def dis(pickle, out=None, indentlevel=4):
18951901
# (which in turn is needed to indent MARK blocks correctly).
18961902

18971903
stack = [] # crude emulation of unpickler stack
1898-
memo = {} # crude emulation of unpicker memo
1904+
if memo is None:
1905+
memo = {} # crude emulation of unpicker memo
18991906
maxproto = -1 # max protocol number seen
19001907
markstack = [] # bytecode positions of MARK opcodes
19011908
indentchunk = ' ' * indentlevel
@@ -2195,7 +2202,36 @@ def dis(pickle, out=None, indentlevel=4):
21952202
highest protocol among opcodes = 2
21962203
"""
21972204

2205+
_memo_test = r"""
2206+
>>> import pickle
2207+
>>> from StringIO import StringIO
2208+
>>> f = StringIO()
2209+
>>> p = pickle.Pickler(f, 2)
2210+
>>> x = [1, 2, 3]
2211+
>>> p.dump(x)
2212+
>>> p.dump(x)
2213+
>>> f.seek(0)
2214+
>>> memo = {}
2215+
>>> dis(f, memo=memo)
2216+
0: \x80 PROTO 2
2217+
2: ] EMPTY_LIST
2218+
3: q BINPUT 0
2219+
5: ( MARK
2220+
6: K BININT1 1
2221+
8: K BININT1 2
2222+
10: K BININT1 3
2223+
12: e APPENDS (MARK at 5)
2224+
13: . STOP
2225+
highest protocol among opcodes = 2
2226+
>>> dis(f, memo=memo)
2227+
14: \x80 PROTO 2
2228+
16: h BINGET 0
2229+
18: . STOP
2230+
highest protocol among opcodes = 2
2231+
"""
2232+
21982233
__test__ = {'disassembler_test': _dis_test,
2234+
'disassembler_memo_test': _memo_test,
21992235
}
22002236

22012237
def _test():

0 commit comments

Comments
 (0)