diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2009-10-19 06:55:03 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2009-10-19 06:55:03 -0400 |
commit | 832ee468e711e6d33fb49fb718e60a85c970a8ef (patch) | |
tree | 048ed03bbec8096b58f6123a5b81cba1ef684f5a /coverage/parser.py | |
parent | 352324b4df27881776ceeb9584574081691a477e (diff) | |
download | python-coveragepy-git-832ee468e711e6d33fb49fb718e60a85c970a8ef.tar.gz |
Start testing exceptions with arc measurements.
Diffstat (limited to 'coverage/parser.py')
-rw-r--r-- | coverage/parser.py | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/coverage/parser.py b/coverage/parser.py index 99656f17..74490189 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -171,20 +171,32 @@ class CodeParser: arcs = self.byte_parser._all_arcs() return sorted(arcs) -# Opcodes that guide the ByteParser. +## Opcodes that guide the ByteParser. def _opcode_set(*names): return set([opcode.opmap[name] for name in names]) +# Opcodes that leave the code object. OPS_CODE_END = _opcode_set('RETURN_VALUE') + +# Opcodes that unconditionally end the code chunk. OPS_CHUNK_END = _opcode_set( 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'RETURN_VALUE', 'RAISE_VARARGS', 'BREAK_LOOP', 'CONTINUE_LOOP', ) + +# Opcodes that push a block on the block stack. OPS_PUSH_BLOCK = _opcode_set('SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY') + +# Opcodes that pop a block from the block stack. OPS_POP_BLOCK = _opcode_set('POP_BLOCK') + +# Opcodes that break a loop. OPS_BREAK = _opcode_set('BREAK_LOOP') +# Opcodes that have a jump destination, but aren't really a jump. +OPS_NO_JUMP = _opcode_set('SETUP_EXCEPT', 'SETUP_FINALLY') + class ByteParser: """Parse byte codes to understand the structure of code.""" @@ -325,17 +337,24 @@ class ByteParser: chunks.append(chunk) # Look at the opcode - if bc.jump_to >= 0: + if bc.jump_to >= 0 and bc.op not in OPS_NO_JUMP: + # The opcode has a jump, it's an exit for this chunk. chunk.exits.add(bc.jump_to) if bc.op in OPS_CODE_END: + # The opcode can exit the code object. chunk.exits.add(-1) elif bc.op in OPS_PUSH_BLOCK: + # The opcode adds a block to the block_stack. block_stack.append(bc.jump_to) elif bc.op in OPS_POP_BLOCK: + # The opcode pops a block from the block stack. block_stack.pop() elif bc.op in OPS_CHUNK_END: + # This opcode forces the end of the chunk. if bc.op in OPS_BREAK: + # A break is implicit: jump where the top of the + # block_stack points. chunk.exits.add(block_stack[-1]) chunk = None |