[Python-checkins] python/nondist/sandbox/pickletools pickletools.py,1.25,1.26
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Sun, 26 Jan 2003 16:19:52 -0800
Update of /cvsroot/python/python/nondist/sandbox/pickletools
In directory sc8-pr-cvs1:/tmp/cvs-serv11749
Modified Files:
pickletools.py
Log Message:
Got rid of the Walker base class and the Dis disassembler class. There's
now a genops(pickle) generator instead, and a dis() function. The code is
simpler, faster, and clearer this way.
Index: pickletools.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/pickletools/pickletools.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** pickletools.py 26 Jan 2003 20:04:35 -0000 1.25
--- pickletools.py 27 Jan 2003 00:19:50 -0000 1.26
***************
*** 6,10 ****
# descriptors.
#
! # - A symbolic pickle disassembler.
#
# - A pickle verifier: read a pickle and check it exhaustively for
--- 6,10 ----
# descriptors.
#
! # - A symbolic pickle disassembler (done -- see function dis()).
#
# - A pickle verifier: read a pickle and check it exhaustively for
***************
*** 1365,1449 ****
##############################################################################
! # A pickle walker base clase.
!
! class Walker:
! def __init__(self, pickle):
! """pickle is a file-like object containing a pickle bytestream.
!
! Invoking walk() traverses the pickle, calling visit() for each
! opcode encountered, then calling done() once at the end. Subclasses
! will want to override visit(), and possibly done(). The default
! implementations do nothing.
! """
! self.pickle = pickle
! if hasattr(pickle, 'tell'):
! def position():
! return pickle.tell()
! else:
! def position():
! return None
! self.position = position
! def walk(self):
! """"Run" the pickle, from the current position, until a STOP opcode.
! For each opcode encountered, calls
! self.visit(opcode, arg, pos)
! opcode is an OpcodeInfo record, describing the current opcode.
! If the opcode has an argument embedded in the pickle, arg contains
! its decoded value, as a Python object. If the opcode doesn't have
! an argument, arg is None.
! If the pickle has a tell() method, pos was the value of pickle.tell()
! before reading the current opcode. Else pos is None.
! After a STOP opcode triggers a visit() call, self.done() is called
! once.
! """
! pickle = self.pickle
! position = self.position
! while True:
! pos = position()
! code = pickle.read(1)
! opcode = code2op.get(code)
! if opcode is None:
! if code == "":
! raise ValueError("pickle exhausted before seeing STOP")
! else:
! raise ValueError("at position %s, opcode %r unknown" % (
! pos is None and "<unknown>" or pos,
! code))
! if opcode.arg is None:
! arg = None
else:
! arg = opcode.arg.reader(pickle)
! self.visit(opcode, arg, pos)
! if code == '.':
! assert opcode.name == 'STOP'
! break
! self.done()
! def visit(self, opcode, arg, pos):
! "Called once per opcode. See the walk() docs for argument details."
! pass
! def done(self):
! "Called after STOP is passed to visit()."
! pass
! class Dis(Walker):
! def __init__(self, pickle, out=None):
! Walker.__init__(self, pickle)
! self.out = out
! def visit(self, opcode, arg, pos):
! out = self.out
if pos is not None:
print >> out, "%5d:" % pos,
--- 1365,1439 ----
##############################################################################
! # A pickle opcode generator.
! def genops(pickle):
! """"Generate all the opcodes in a pickle.
! 'pickle' is a file-like object, or string, containing the pickle.
! Each opcode in the pickle is generated, from the current pickle position,
! stopping after a STOP opcode is delivered. A triple is generated for
! each opcode:
! opcode, arg, pos
! opcode is an OpcodeInfo record, describing the current opcode.
! If the opcode has an argument embedded in the pickle, arg is its decoded
! value, as a Python object. If the opcode doesn't have an argument, arg
! is None.
! If the pickle has a tell() method, pos was the value of pickle.tell()
! before reading the current opcode. If the pickle is a string object,
! it's wrapped in a StringIO object, and the latter's tell() result is
! used. Else (the pickle doesn't have a tell(), and it's not obvious how
! to query its current position) pos is None.
! """
! import cStringIO as StringIO
! if isinstance(pickle, str):
! pickle = StringIO.StringIO(pickle)
! if hasattr(pickle, "tell"):
! getpos = pickle.tell
! else:
! getpos = lambda: None
! while True:
! pos = getpos()
! code = pickle.read(1)
! opcode = code2op.get(code)
! if opcode is None:
! if code == "":
! raise ValueError("pickle exhausted before seeing STOP")
else:
! raise ValueError("at position %s, opcode %r unknown" % (
! pos is None and "<unknown>" or pos,
! code))
! if opcode.arg is None:
! arg = None
! else:
! arg = opcode.arg.reader(pickle)
! yield opcode, arg, pos
! if code == '.':
! assert opcode.name == 'STOP'
! break
! ##############################################################################
! # A symbolic pickle disassembler.
! def dis(pickle, out=None):
! """Produce a symbolic disassembly of a pickle.
! 'pickle' is file-like object, or string, containing a (at least one)
! pickle. The pickle is disassembled from the current position, through
! the first STOP opcode encountered.
! Optional arg 'out' is a file-like object to which the disassembly is
! printed. It defaults to sys.stdout.
! """
!
! for opcode, arg, pos in genops(pickle):
if pos is not None:
print >> out, "%5d:" % pos,
***************
*** 1455,1465 ****
_disassembler_test = """
- >>> from StringIO import StringIO
>>> import pickle
>>> x = [1, 2, (3, 4), {'abc': u"def"}]
>>> pik = pickle.dumps(x)
! >>> stream = StringIO(pik)
! >>> d = Dis(stream)
! >>> d.walk()
0: ( MARK
1: l LIST
--- 1445,1452 ----
_disassembler_test = """
>>> import pickle
>>> x = [1, 2, (3, 4), {'abc': u"def"}]
>>> pik = pickle.dumps(x)
! >>> dis(pik)
0: ( MARK
1: l LIST
***************
*** 1487,1494 ****
Try again with a "binary" pickle.
>>> pik = pickle.dumps(x, 1)
! >>> stream = StringIO(pik)
! >>> d = Dis(stream)
! >>> d.walk()
0: ] EMPTY_LIST
1: q BINPUT 0
--- 1474,1480 ----
Try again with a "binary" pickle.
+
>>> pik = pickle.dumps(x, 1)
! >>> dis(pik)
0: ] EMPTY_LIST
1: q BINPUT 0