1import dis
2import array
3import collections
4
5try:
6 import html
7except ImportError:
8 html = None
9
10from setuptools.extern import six
11from setuptools.extern.six.moves import html_parser
12
13__metaclass__ = type
14
15OpArg = collections.namedtuple('OpArg', 'opcode arg')
16
17
18class Bytecode_compat:
19 def __init__(self, code):
20 self.code = code
21
22 def __iter__(self):
23 """Yield '(op,arg)' pair for each operation in code object 'code'"""
24
25 bytes = array.array('b', self.code.co_code)
26 eof = len(self.code.co_code)
27
28 ptr = 0
29 extended_arg = 0
30
31 while ptr < eof:
32
33 op = bytes[ptr]
34
35 if op >= dis.HAVE_ARGUMENT:
36
37 arg = bytes[ptr + 1] + bytes[ptr + 2] * 256 + extended_arg
38 ptr += 3
39
40 if op == dis.EXTENDED_ARG:
41 long_type = six.integer_types[-1]
42 extended_arg = arg * long_type(65536)
43 continue
44
45 else:
46 arg = None
47 ptr += 1
48
49 yield OpArg(op, arg)
50
51
52Bytecode = getattr(dis, 'Bytecode', Bytecode_compat)
53
54
55unescape = getattr(html, 'unescape', None)
56if unescape is None:
57 # HTMLParser.unescape is deprecated since Python 3.4, and will be removed
58 # from 3.9.
59 unescape = html_parser.HTMLParser().unescape