summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2013-01-08 09:57:24 -0500
committerNed Batchelder <ned@nedbatchelder.com>2013-01-08 09:57:24 -0500
commit11829e9fe0b190e0ac4ce52a98553142782b3ff6 (patch)
treebaf7c5ab00f90050f3a9d4708dc2110747aefa20
parent562e0493d521fd8c7972d6edc8d7e52780505fa8 (diff)
downloadpython-coveragepy-git-11829e9fe0b190e0ac4ce52a98553142782b3ff6.tar.gz
Use generators in the byte code parsing. __next__? yikes!
-rw-r--r--coverage/bytecode.py52
-rw-r--r--coverage/parser.py15
2 files changed, 25 insertions, 42 deletions
diff --git a/coverage/bytecode.py b/coverage/bytecode.py
index fd5c7da2..06bc1dfd 100644
--- a/coverage/bytecode.py
+++ b/coverage/bytecode.py
@@ -30,7 +30,6 @@ class ByteCodes(object):
# pylint: disable=R0924
def __init__(self, code):
self.code = code
- self.offset = 0
if sys.version_info >= (3, 0):
def __getitem__(self, i):
@@ -40,32 +39,26 @@ class ByteCodes(object):
return ord(self.code[i])
def __iter__(self):
- return self
+ offset = 0
+ while offset < len(self.code):
+ bc = ByteCode()
+ bc.op = self[offset]
+ bc.offset = offset
- def __next__(self):
- if self.offset >= len(self.code):
- raise StopIteration
+ next_offset = offset+1
+ if bc.op >= opcode.HAVE_ARGUMENT:
+ bc.arg = self[offset+1] + 256*self[offset+2]
+ next_offset += 2
- bc = ByteCode()
- bc.op = self[self.offset]
- bc.offset = self.offset
+ label = -1
+ if bc.op in opcode.hasjrel:
+ label = next_offset + bc.arg
+ elif bc.op in opcode.hasjabs:
+ label = bc.arg
+ bc.jump_to = label
- next_offset = self.offset+1
- if bc.op >= opcode.HAVE_ARGUMENT:
- bc.arg = self[self.offset+1] + 256*self[self.offset+2]
- next_offset += 2
-
- label = -1
- if bc.op in opcode.hasjrel:
- label = next_offset + bc.arg
- elif bc.op in opcode.hasjabs:
- label = bc.arg
- bc.jump_to = label
-
- bc.next_offset = self.offset = next_offset
- return bc
-
- next = __next__ # Py2k uses an old-style non-dunder name.
+ bc.next_offset = offset = next_offset
+ yield bc
class CodeObjects(object):
@@ -74,18 +67,11 @@ class CodeObjects(object):
self.stack = [code]
def __iter__(self):
- return self
-
- def __next__(self):
- if self.stack:
+ while 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__
+ yield code
diff --git a/coverage/parser.py b/coverage/parser.py
index 44455054..bb6b6082 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -381,27 +381,25 @@ class ByteParser(object):
"""Map byte offsets to line numbers in `code`.
Uses co_lnotab described in Python/compile.c to map byte offsets to
- line numbers. Returns a list: [(b0, l0), (b1, l1), ...]
+ line numbers. Produces a sequence: (b0, l0), (b1, l1), ...
"""
# Adapted from dis.py in the standard library.
byte_increments = self._lnotab_increments(self.code.co_lnotab[0::2])
line_increments = self._lnotab_increments(self.code.co_lnotab[1::2])
- bytes_lines = []
last_line_num = None
line_num = self.code.co_firstlineno
byte_num = 0
for byte_incr, line_incr in zip(byte_increments, line_increments):
if byte_incr:
if line_num != last_line_num:
- bytes_lines.append((byte_num, line_num))
+ yield (byte_num, line_num)
last_line_num = line_num
byte_num += byte_incr
line_num += line_incr
if line_num != last_line_num:
- bytes_lines.append((byte_num, line_num))
- return bytes_lines
+ yield (byte_num, line_num)
def _find_statements(self):
"""Find the statements in `self.code`.
@@ -426,7 +424,6 @@ class ByteParser(object):
Returns a list of `Chunk` objects.
"""
-
# The list of chunks so far, and the one we're working on.
chunks = []
chunk = None
@@ -634,11 +631,11 @@ class ByteParser(object):
class Chunk(object):
- """A sequence of bytecodes with a single entrance.
+ """A sequence of byte codes with a single entrance.
To analyze byte code, we have to divide it into chunks, sequences of byte
- codes such that each basic block has only one entrance, the first
- instruction in the block.
+ codes such that each chunk has only one entrance, the first instruction in
+ the block.
This is almost the CS concept of `basic block`_, except that we're willing
to have many exits from a chunk, and "basic block" is a more cumbersome