def test_opcode(): opc = get_opcode(PYTHON_VERSION, IS_PYPY) opmap = dict([(k.replace('+', '_'), v) for (k, v) in dis.opmap.items()]) print("Extra in dis:", set(opmap.items()) - set(opc.opmap.items())) print("Extra in xdis:", set(opc.opmap.items()) - set(opmap.items())) for item in opmap.items(): assert item in opc.opmap.items(), item fields_str = "hascompare hasconst hasfree hasjabs hasjrel haslocal" # PyPy 2.7.13 changes opcodes mid-version. It is too complicated # to figure out where the change actually occurred # Pypy 3.6.9 may or may not have JUMP_IF_NOT_DEBUG if not (IS_PYPY and PYTHON_VERSION in (2.7, 3.6)): assert all(item in opmap.items() for item in opc.opmap.items()) elif (IS_PYPY and PYTHON_VERSION == 3.6): # Don't count JUMP_IF_NOT_DEBUG mismatch fields_str = "hascompare hasconst hasfree hasjabs haslocal" assert all(item in opc.opmap.items() for item in opmap.items()) fields = fields_str.split() for field in fields: opc_set = set(getattr(opc, field)) dis_set = set(getattr(dis, field)) assert opc_set == dis_set, \ ("diff in %s: %s" % (field, ', '.join([opc.opname[i] for i in list(opc_set ^ dis_set)])))
def test_opcode(): opc = get_opcode(PYTHON_VERSION, IS_PYPY) opmap = dict([(k.replace('+', '_'), v) for (k, v) in dis.opmap.items()]) # print(set(opmap.items()) - set(opc.opmap.items())) # print(set(opc.opmap.items()) - set(opmap.items())) # for item in opmap.items(): # assert item in opc.opmap.items(), item # PyPy 2.7.13 changes opcodes mid-version. It is too complicated # to figure out where the change actually occurred if not (IS_PYPY and PYTHON_VERSION == 2.7): assert all(item in opmap.items() for item in opc.opmap.items()) assert all(item in opc.opmap.items() for item in opmap.items()) fields = """hascompare hasconst hasfree hasjabs hasjrel haslocal hasname""".split() for field in fields: opc_set = set(getattr(opc, field)) dis_set = set(getattr(dis, field)) assert opc_set == dis_set, \ ("diff in %s: %s" % (field, ', '.join([opc.opname[i] for i in list(opc_set ^ dis_set)])))
def line_number_mapping(pyc_filename, src_filename): (version, timestamp, magic_int, code1, is_pypy, source_size) = load_module(pyc_filename) try: code2 = load_file(src_filename) except SyntaxError as e: return str(e) queue = deque([code1, code2]) mappings = [] opc = get_opcode(version, is_pypy) number_loop(queue, mappings, opc) return sorted(mappings, key=lambda x: x[1])
def test_opcode(): opc = get_opcode(PYTHON_VERSION, IS_PYPY) opmap = dict([(k.replace('+', '_'), v) for (k, v) in dis.opmap.items()]) # print(set(opmap.items()) - set(l['opmap'].items())) # print(set(l['opmap'].items()) - set(opmap.items())) assert all(item in opmap.items() for item in opc.opmap.items()) assert all(item in opc.opmap.items() for item in opmap.items()) fields = """hascompare hasconst hasfree hasjabs hasjrel haslocal hasname""".split() for field in fields: opc_set = set(getattr(opc, field)) dis_set = set(getattr(dis, field)) assert opc_set == dis_set, \ ("diff in %s: %s" % (field, ', '.join([opc.opname[i] for i in list(opc_set ^ dis_set)])))
# future from __future__ import print_function # std import os import difflib import subprocess import tempfile import functools # compatability import six # uncompyle6 / xdis from uncompyle6 import PYTHON_VERSION, IS_PYPY, deparse_code # TODO : I think we can get xdis to support the dis api (python 3 version) by doing something like this there from xdis.bytecode import Bytecode from xdis.main import get_opcode opc = get_opcode(PYTHON_VERSION, IS_PYPY) Bytecode = functools.partial(Bytecode, opc=opc) def _dis_to_text(co): return Bytecode(co).dis() def print_diff(original, uncompyled): """ Try and display a pretty html line difference between the original and uncompyled code and bytecode if elinks and BeautifulSoup are installed otherwise just show the diff. :param original: Text describing the original code object. :param uncompyled: Text describing the uncompyled code object.
def dis(msg, msg_nocr, section, errmsg, x=None, start_line=-1, end_line=None, relative_pos = False, highlight='light', start_offset=0, end_offset=None, include_header=False): """Disassemble classes, methods, functions, or code. With no argument, disassemble the last traceback. """ lasti = -1 if x is None: distb() return None, None if start_offset is None: start_offset = 0 mess = '' if start_line > 1: mess += "from line %d " % start_line elif start_offset > 1: mess = "from offset %d " % start_offset if end_line: mess += "to line %d" % end_line elif end_offset: mess += "to offset %d" % end_offset sectioned = False # Try to dogpaddle to the code object for the type setting x if hasattr(types, 'InstanceType') and isinstance(x, types.InstanceType): x = x.__class__ if inspect.ismethod(x): section("Disassembly of %s: %s" % (x, mess)) sectioned = True x = x.im_func elif inspect.isfunction(x) or inspect.isgeneratorfunction(x): section("Disassembly of %s: %s" % (x, mess)) x = x.func_code sectioned = True elif inspect.isgenerator(x): section("Disassembly of %s: %s" % (x, mess)) frame = x.gi_frame lasti = frame.f_last_i x = x.gi_code sectioned = True elif inspect.isframe(x): section("Disassembly of %s: %s" % (x, mess)) sectioned = True if hasattr(x, 'f_lasti'): lasti = x.f_lasti if lasti == -1: lasti = 0 pass opc = get_opcode(PYTHON_VERSION, IS_PYPY) x = x.f_code if include_header: header_lines = Bytecode(x, opc).info().split("\n") header = '\n'.join([format_token(Mformat.Comment, h) for h in header_lines]) msg(header) pass elif inspect.iscode(x): pass if hasattr(x, '__dict__'): # Class or module items = sorted(x.__dict__.items()) for name, x1 in items: if isinstance(x1, _have_code): if not sectioned: section("Disassembly of %s: " % x) try: dis(msg, msg_nocr, section, errmsg, x1, start_line=start_line, end_line=end_line, relative_pos = relative_pos) msg("") except TypeError: _, msg, _ = sys.exc_info() errmsg("Sorry:", msg) pass pass pass pass elif hasattr(x, 'co_code'): # Code object if not sectioned: section("Disassembly of %s: " % x) return disassemble(msg, msg_nocr, section, x, lasti=lasti, start_line=start_line, end_line=end_line, relative_pos = relative_pos, highlight = highlight, start_offset = start_offset, end_offset = end_offset) elif isinstance(x, str): # Source code return disassemble_string(msg, msg_nocr, x,) else: errmsg("Don't know how to disassemble %s objects." % type(x).__name__) return None, None