From 733b74c1a5c72afb485d1ed9826310319dee96e7 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 10 Oct 2009 10:43:16 -0400 Subject: Need this too --- coverage/bytecode.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 coverage/bytecode.py (limited to 'coverage/bytecode.py') diff --git a/coverage/bytecode.py b/coverage/bytecode.py new file mode 100644 index 00000000..0680a57f --- /dev/null +++ b/coverage/bytecode.py @@ -0,0 +1,81 @@ +"""Bytecode manipulation for coverage.py""" + +import opcode, sys, types + +class ByteCode(object): + """A single bytecode.""" + def __init__(self): + self.offset = -1 + self.op = -1 + self.oparg = -1 + self.next_offset = -1 + self.jump_to = -1 + + +class ByteCodes(object): + """Iterator over byte codes in `code`. + + Returns `ByteCode` objects. + + """ + def __init__(self, code): + self.code = code + self.offset = 0 + + if sys.hexversion > 0x03000000: + def byte_at(self, i): + return self.code[i] + else: + def byte_at(self, i): + return ord(self.code[i]) + + def __iter__(self): + return self + + def __next__(self): + if self.offset >= len(self.code): + raise StopIteration + + bc = ByteCode() + bc.op = self.byte_at(self.offset) + bc.offset = self.offset + + next_offset = self.offset+1 + if bc.op >= opcode.HAVE_ARGUMENT: + bc.oparg = self.byte_at(self.offset+1) + 256*self.byte_at(self.offset+2) + next_offset += 2 + + label = -1 + if bc.op in opcode.hasjrel: + label = next_offset + bc.oparg + elif bc.op in opcode.hasjabs: + label = bc.oparg + bc.jump_to = label + + bc.next_offset = self.offset = next_offset + return bc + + next = __next__ # Py2k uses an old-style non-dunder name. + + +class CodeObjects(object): + """Iterate over all the code objects in `code`.""" + def __init__(self, code): + self.stack = [code] + + def __iter__(self): + return self + + def __next__(self): + if self.stack: + # We're going to return the code object on the stack, but first + # push its children for later returning. + code = self.stack.pop() + for c in code.co_consts: + if isinstance(c, types.CodeType): + self.stack.append(c) + return code + + raise StopIteration + + next = __next__ -- cgit v1.2.1