summaryrefslogtreecommitdiff
path: root/coverage/bytecode.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2009-10-10 10:43:16 -0400
committerNed Batchelder <ned@nedbatchelder.com>2009-10-10 10:43:16 -0400
commit31fe60bfcf3462a327c8fc34a9fe96bad343c741 (patch)
tree1dfeff929835d99884116f455b1186007c1b98ff /coverage/bytecode.py
parent1656caa3e3f28c57cad1498b5ec0471b8bcee48e (diff)
downloadpython-coveragepy-31fe60bfcf3462a327c8fc34a9fe96bad343c741.tar.gz
Need this too
Diffstat (limited to 'coverage/bytecode.py')
-rw-r--r--coverage/bytecode.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/coverage/bytecode.py b/coverage/bytecode.py
new file mode 100644
index 0000000..0680a57
--- /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__