DebugClients/Python/coverage/bytecode.py

changeset 31
744cd0b4b8cd
child 790
2c0ea0163ef4
equal deleted inserted replaced
30:9513afbd57f1 31:744cd0b4b8cd
1 """Bytecode manipulation for coverage.py"""
2
3 import opcode, sys, types
4
5 class ByteCode(object):
6 """A single bytecode."""
7 def __init__(self):
8 self.offset = -1
9 self.op = -1
10 self.arg = -1
11 self.next_offset = -1
12 self.jump_to = -1
13
14
15 class ByteCodes(object):
16 """Iterator over byte codes in `code`.
17
18 Returns `ByteCode` objects.
19
20 """
21 def __init__(self, code):
22 self.code = code
23 self.offset = 0
24
25 if sys.hexversion > 0x03000000:
26 def __getitem__(self, i):
27 return self.code[i]
28 else:
29 def __getitem__(self, i):
30 return ord(self.code[i])
31
32 def __iter__(self):
33 return self
34
35 def __next__(self):
36 if self.offset >= len(self.code):
37 raise StopIteration
38
39 bc = ByteCode()
40 bc.op = self[self.offset]
41 bc.offset = self.offset
42
43 next_offset = self.offset+1
44 if bc.op >= opcode.HAVE_ARGUMENT:
45 bc.arg = self[self.offset+1] + 256*self[self.offset+2]
46 next_offset += 2
47
48 label = -1
49 if bc.op in opcode.hasjrel:
50 label = next_offset + bc.arg
51 elif bc.op in opcode.hasjabs:
52 label = bc.arg
53 bc.jump_to = label
54
55 bc.next_offset = self.offset = next_offset
56 return bc
57
58 next = __next__ # Py2k uses an old-style non-dunder name.
59
60
61 class CodeObjects(object):
62 """Iterate over all the code objects in `code`."""
63 def __init__(self, code):
64 self.stack = [code]
65
66 def __iter__(self):
67 return self
68
69 def __next__(self):
70 if self.stack:
71 # We're going to return the code object on the stack, but first
72 # push its children for later returning.
73 code = self.stack.pop()
74 for c in code.co_consts:
75 if isinstance(c, types.CodeType):
76 self.stack.append(c)
77 return code
78
79 raise StopIteration
80
81 next = __next__

eric ide

mercurial