| import dis | |
| import io | |
| import marshal | |
| import os | |
| import sys | |
| import textwrap | |
| from bytecode import fix_spacing, format_bytecode | |
| def disassemble_pyc_file(pyc_file) -> str: | |
| with open(pyc_file, "rb") as f: | |
| header = f.read(16) | |
| magic_number = header[:2] | |
| if 3394 != int.from_bytes(magic_number, "little"): | |
| print(f"{pyc_file} not compiled with Python 3.7") | |
| return None | |
| bytecode = marshal.load(f) | |
| original_stdout = sys.stdout | |
| string_output = io.StringIO() | |
| sys.stdout = string_output | |
| dis.dis(bytecode) | |
| sys.stdout = original_stdout | |
| disassembled_pyc = string_output.getvalue() | |
| byte_code = fix_spacing(textwrap.dedent(str(disassembled_pyc)).strip()) | |
| formatted_bytecode = format_bytecode(bytecode=byte_code) | |
| return formatted_bytecode | |
| def convert_pyc_to_bytecode(file_path: str): | |
| formatted_bytecode = disassemble_pyc_file(file_path) | |
| if formatted_bytecode is None: | |
| return | |
| with open(file_path + "b", "w") as bytecode_file: | |
| print(f"Converted {file_path} to bytecode") | |
| bytecode_file.write(formatted_bytecode) | |
| if __name__ == "__main__": | |
| path = sys.argv[1] | |
| if os.path.isfile(path) and path.endswith(".pyc"): | |
| convert_pyc_to_bytecode(path) | |
| elif os.path.isdir(path): | |
| for root, _, files in os.walk(path): | |
| for file in files: | |
| file_path = os.path.join(root, file) | |
| if not file.endswith(".pyc"): | |
| continue | |
| convert_pyc_to_bytecode(file_path) | |