|
import dis |
|
import io |
|
import re |
|
import sys |
|
import textwrap |
|
from op_codes import op_codes_37 |
|
|
|
|
|
def fix_spacing(unformatted_decompiled_python): |
|
decompiled_python = re.sub(r"[ \t]+", " ", unformatted_decompiled_python) |
|
decompiled_python = re.sub(r"\n ", "\n", decompiled_python) |
|
return decompiled_python |
|
|
|
|
|
def get_byte_code(python_code): |
|
code_object = compile(python_code, "f.py", "exec") |
|
|
|
original_stdout = sys.stdout |
|
string_output = io.StringIO() |
|
sys.stdout = string_output |
|
dis.dis(code_object) |
|
sys.stdout = original_stdout |
|
disassembled_pyc = string_output.getvalue() |
|
return fix_spacing(textwrap.dedent(str(disassembled_pyc)).strip()) |
|
|
|
|
|
def extract_text_between_parentheses(input_string): |
|
start_index = input_string.find("(") |
|
end_index = input_string.rfind(")") |
|
|
|
if start_index != -1 and end_index != -1 and start_index < end_index: |
|
return input_string[start_index + 1 : end_index] |
|
else: |
|
return "" |
|
|
|
|
|
def reformat_bytecode_line(input_string): |
|
if input_string.startswith("Disassembly of <"): |
|
return None |
|
|
|
for code in op_codes_37: |
|
if code in input_string: |
|
reformatted_string = extract_text_between_parentheses(input_string) |
|
return f"{code} {reformatted_string}".strip() |
|
|
|
return input_string |
|
|
|
|
|
def format_bytecode(bytecode: str): |
|
formatted_strings = [] |
|
for line in bytecode.split("\n"): |
|
reformatted_string = reformat_bytecode_line(line) |
|
if reformatted_string is not None: |
|
formatted_strings.append(reformatted_string) |
|
return "\n".join(formatted_strings).strip() |
|
|
|
|
|
if __name__ == "__main__": |
|
file_path = sys.argv[1] |
|
print(f"Converting python source code to byte code {file_path}") |
|
with open(file_path, "r") as file: |
|
file_contents = file.read() |
|
print(file_contents) |
|
byte_code = get_byte_code(file_contents) |
|
|
|
print(format_bytecode(bytecode=byte_code)) |
|
|