DebugClients/Python/coverage/bytecode.py

Sat, 28 Mar 2015 12:11:11 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 28 Mar 2015 12:11:11 +0100
branch
6_0_x
changeset 4188
447bd181896b
parent 3499
f2d4b02c7e88
child 4489
d0d6e4ad31bd
permissions
-rw-r--r--

Fixed an issue in the Python debug clients causing unit tests to fail for threaded code (s. issue 178).
(grafted from 61fd08bac49ba3ce2bc15f897c7651b61f32077f)

"""Bytecode manipulation for coverage.py"""

import opcode, types

from .backward import byte_to_int

class ByteCode(object):
    """A single bytecode."""
    def __init__(self):
        # The offset of this bytecode in the code object.
        self.offset = -1

        # The opcode, defined in the `opcode` module.
        self.op = -1

        # The argument, a small integer, whose meaning depends on the opcode.
        self.arg = -1

        # The offset in the code object of the next bytecode.
        self.next_offset = -1

        # The offset to jump to.
        self.jump_to = -1


class ByteCodes(object):
    """Iterator over byte codes in `code`.

    Returns `ByteCode` objects.

    """
    # pylint: disable=R0924
    def __init__(self, code):
        self.code = code

    def __getitem__(self, i):
        return byte_to_int(self.code[i])

    def __iter__(self):
        offset = 0
        while offset < len(self.code):
            bc = ByteCode()
            bc.op = self[offset]
            bc.offset = offset

            next_offset = offset+1
            if bc.op >= opcode.HAVE_ARGUMENT:
                bc.arg = self[offset+1] + 256*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 = offset = next_offset
            yield bc


class CodeObjects(object):
    """Iterate over all the code objects in `code`."""
    def __init__(self, code):
        self.stack = [code]

    def __iter__(self):
        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)
            yield code

#
# eflag: FileType = Python2

eric ide

mercurial