Ejemplo n.º 1
0
def decompile(bytecode_version,
              co,
              out=None,
              showasm=None,
              showast=False,
              timestamp=None,
              showgrammar=False,
              code_objects={},
              source_size=None,
              is_pypy=None,
              magic_int=None,
              mapstream=None,
              do_fragments=False):
    """
    ingests and deparses a given code block 'co'

    if `bytecode_version` is None, use the current Python intepreter
    version.

    Caller is responsible for closing `out` and `mapstream`
    """
    if bytecode_version is None:
        bytecode_version = sysinfo2float()

    # store final output stream for case of error
    real_out = out or sys.stdout

    def write(s):
        s += '\n'
        real_out.write(s)

    assert iscode(co)

    co_pypy_str = 'PyPy ' if is_pypy else ''
    run_pypy_str = 'PyPy ' if IS_PYPY else ''
    sys_version_lines = sys.version.split('\n')
    write('# decompyle3 version %s\n'
          '# %sPython bytecode %s%s\n# Decompiled from: %sPython %s' %
          (VERSION, co_pypy_str, bytecode_version, " (%s)" % str(magic_int)
           if magic_int else "", run_pypy_str, '\n# '.join(sys_version_lines)))
    if co.co_filename:
        write('# Embedded file name: %s' % co.co_filename, )
    if timestamp:
        write('# Compiled at: %s' % datetime.datetime.fromtimestamp(timestamp))
    if source_size:
        write('# Size of source mod 2**32: %d bytes' % source_size)

    debug_opts = {'asm': showasm, 'ast': showast, 'grammar': showgrammar}

    try:
        if mapstream:
            if isinstance(mapstream, str):
                mapstream = _get_outstream(mapstream)

            deparsed = deparse_code_with_map(
                bytecode_version,
                co,
                out,
                showasm,
                showast,
                showgrammar,
                code_objects=code_objects,
                is_pypy=is_pypy,
            )
            header_count = 3 + len(sys_version_lines)
            linemap = [(line_no,
                        deparsed.source_linemap[line_no] + header_count)
                       for line_no in sorted(deparsed.source_linemap.keys())]
            mapstream.write("\n\n# %s\n" % linemap)
        else:
            if do_fragments:
                deparse_fn = code_deparse_fragments
            else:
                deparse_fn = code_deparse
            deparsed = deparse_fn(co,
                                  out,
                                  bytecode_version,
                                  debug_opts=debug_opts,
                                  is_pypy=is_pypy)
            pass
        return deparsed
    except pysource.SourceWalkerError as e:
        # deparsing failed
        raise pysource.SourceWalkerError(str(e))
Ejemplo n.º 2
0
def decompile(
    bytecode_version: str,
    co,
    out=None,
    showasm=None,
    showast={},
    timestamp=None,
    showgrammar=False,
    source_encoding=None,
    code_objects={},
    source_size=None,
    is_pypy=None,
    magic_int=None,
    mapstream=None,
    do_fragments=False,
    compile_mode="exec",
) -> Any:
    """
    ingests and deparses a given code block 'co'

    if `bytecode_version` is None, use the current Python intepreter
    version.

    Caller is responsible for closing `out` and `mapstream`
    """
    if bytecode_version is None:
        bytecode_version = sysinfo2float()

    # store final output stream for case of error
    real_out = out or sys.stdout

    def write(s):
        s += "\n"
        real_out.write(s)

    assert iscode(co), f"""{co} is not smell like code"""

    co_pypy_str = "PyPy " if is_pypy else ""
    run_pypy_str = "PyPy " if IS_PYPY else ""
    sys_version_lines = sys.version.split("\n")
    if source_encoding:
        write("# -*- coding: %s -*-" % source_encoding)
    write("# decompyle3 version %s\n"
          "# %sPython bytecode %s%s\n# Decompiled from: %sPython %s" % (
              __version__,
              co_pypy_str,
              bytecode_version,
              " (%s)" % str(magic_int) if magic_int else "",
              run_pypy_str,
              "\n# ".join(sys_version_lines),
          ))
    if co.co_filename:
        write("# Embedded file name: %s" % co.co_filename)
    if timestamp:
        write("# Compiled at: %s" % datetime.datetime.fromtimestamp(timestamp))
    if source_size:
        write("# Size of source mod 2**32: %d bytes" % source_size)

    debug_opts = {"asm": showasm, "ast": showast, "grammar": showgrammar}

    try:
        if mapstream:
            if isinstance(mapstream, str):
                mapstream = _get_outstream(mapstream)

            deparsed = deparse_code_with_map(
                bytecode_version,
                co,
                out,
                showasm,
                showast,
                showgrammar,
                code_objects=code_objects,
                is_pypy=is_pypy,
            )
            header_count = 3 + len(sys_version_lines)
            linemap = [(line_no,
                        deparsed.source_linemap[line_no] + header_count)
                       for line_no in sorted(deparsed.source_linemap.keys())]
            mapstream.write("\n\n# %s\n" % linemap)
        else:
            if do_fragments:
                deparse_fn = code_deparse_fragments
            else:
                deparse_fn = code_deparse
            deparsed = deparse_fn(
                co,
                out,
                bytecode_version,
                debug_opts=debug_opts,
                is_pypy=is_pypy,
                compile_mode=compile_mode,
            )
            pass
        return deparsed
    except pysource.SourceWalkerError as e:
        # deparsing failed
        raise pysource.SourceWalkerError(str(e))