@@ -1861,7 +1861,7 @@ def genops(pickle):
1861
1861
##############################################################################
1862
1862
# A symbolic pickle disassembler.
1863
1863
1864
- def dis (pickle , out = None , indentlevel = 4 ):
1864
+ def dis (pickle , out = None , memo = None , indentlevel = 4 ):
1865
1865
"""Produce a symbolic disassembly of a pickle.
1866
1866
1867
1867
'pickle' is a file-like object, or string, containing a (at least one)
@@ -1871,6 +1871,12 @@ def dis(pickle, out=None, indentlevel=4):
1871
1871
Optional arg 'out' is a file-like object to which the disassembly is
1872
1872
printed. It defaults to sys.stdout.
1873
1873
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
+
1874
1880
Optional arg indentlevel is the number of blanks by which to indent
1875
1881
a new MARK level. It defaults to 4.
1876
1882
@@ -1895,7 +1901,8 @@ def dis(pickle, out=None, indentlevel=4):
1895
1901
# (which in turn is needed to indent MARK blocks correctly).
1896
1902
1897
1903
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
1899
1906
maxproto = - 1 # max protocol number seen
1900
1907
markstack = [] # bytecode positions of MARK opcodes
1901
1908
indentchunk = ' ' * indentlevel
@@ -2195,7 +2202,36 @@ def dis(pickle, out=None, indentlevel=4):
2195
2202
highest protocol among opcodes = 2
2196
2203
"""
2197
2204
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
+
2198
2233
__test__ = {'disassembler_test' : _dis_test ,
2234
+ 'disassembler_memo_test' : _memo_test ,
2199
2235
}
2200
2236
2201
2237
def _test ():
0 commit comments