Skip to main content

The ChatGPT-powered decompiler for Python, providing superior code analysis capabilities

Project description

PyChD

CI PyPI Version

The ChatGPT-powered decompiler for Python, providing superior code analysis capabilities

Usage

Install

From pip

pip install pychd

Compile

pychd compile <directory | file> # you need to specify a directory or a .py file

E.g.,

pychd compile examples/01_example_variables.py # `example/__pycache__/01_example_variables.cpython-310.pyc` will be created

Decompile

pychd decompile <pyc-file> # you need to specify a .pyc file

E.g.,

pychd decompile example/__pycache__/01_example_variables.cpython-310.pyc # decompiled code will be printed
pychd decompile example/__pycache__/01_example_variables.cpython-310.pyc -o example/__pycache__/01_example_variables.cpython-310.py # decompiled code will be written to `example/__pycache__/01_example_variables.cpython-310.py`

Examples

You can find examples in example directory or below (decompiled code is generated by pychd from Python-3.10-compiled .pyc code).

Variables

original

# Assigning values to variables
name = "John Doe"
age = 30
height = 6.1  # in feet

# Performing operations with variables
age_next_year = age + 1
half_height = height / 2

# Printing variables and their values
print("Name:", name)
print("Age:", age)
print("Height:", height, "feet")
print("Age next year:", age_next_year)
print("Half height:", half_height, "feet")

decompiled

name = 'John Doe'
age = 30
height = 6.1
age_next_year = age + 1
half_height = height / 2

print('Name:', name)
print('Age:', age)
print('Height:', height, 'feet')
print('Age next year:', age_next_year)
print('Half height:', half_height, 'feet')

Data types

original

# Integer
integer_example = 42

# Float
float_example = 3.14

# String
string_example = "Hello, World!"

# List
list_example = [1, 2, 3, 4, 5]

# Tuple
tuple_example = (1, "apple", 3.14)

# Dictionary
dict_example = {
    "name": "John Doe",
    "age": 30,
    "city": "New York"
}

# Set
set_example = {1, 2, 3, 4, 5}

# Boolean
bool_example = True

# Printing the examples
print("Integer:", integer_example)
print("Float:", float_example)
print("String:", string_example)
print("List:", list_example)
print("Tuple:", tuple_example)
print("Dictionary:", dict_example)
print("Set:", set_example)
print("Boolean:", bool_example)

decompiled

integer_example = 42
float_example = 3.14
string_example = 'Hello, World!'
list_example = [1, 2, 3, 4, 5]
tuple_example = (1, 'apple', 3.14)
dict_example = {'name': 'John Doe', 'age': 30, 'city': 'New York'}
set_example = {1, 2, 3, 4, 5}.union(frozenset({1, 2, 3, 4, 5}))
bool_example = True

print('Integer:', integer_example)
print('Float:', float_example)
print('String:', string_example)
print('List:', list_example)
print('Tuple:', tuple_example)
print('Dictionary:', dict_example)
print('Set:', set_example)
print('Boolean:', bool_example)

Conditional statements (if-else)

original

age = 25
country = "USA"
job_status = "employed"
favorite_color = "blue"

if age < 18 or (country == "USA" and favorite_color == "blue"):
    if job_status == "employed":
        print("Minor or USA + blue, employed.")
    elif job_status == "unemployed":
        print("Minor or USA + blue, unemployed.")
    else:
        print("Minor or USA + blue, other status.")
else:
    if job_status == "employed":
        if country != "USA" or favorite_color != "blue":
            print("Not minor, not USA + blue, employed.")
    elif job_status == "unemployed":
        if (country != "USA") ^ (favorite_color != "blue"):
            print("Not minor, not USA + blue, unemployed.")
    else:
        print("Not minor, not USA + blue, other status.")

decompiled

age = 25
country = 'USA'
job_status = 'employed'
favorite_color = 'blue'

if age < 18 or (country == 'USA' and favorite_color == 'blue'):
    if job_status == 'employed':
        print('Minor or USA + blue, employed.')
    else:
        print('Minor or USA + blue, unemployed.')
else:
    if job_status == 'employed':
        if country != 'USA' or favorite_color != 'blue':
            print('Not minor, not USA + blue, employed.')
    else:
        if country != 'USA' or favorite_color != 'blue':
            print('Not minor, not USA + blue, unemployed.')
        else:
            print('Not minor, not USA + blue, other status.')

Loops

original

# Using a for loop to iterate through a list
fruits = ["apple", "banana", "orange", "grape"]
for fruit in fruits:
    print(f"Current fruit: {fruit}")

# Using a for loop with the range function
for i in range(5):
    print(f"Current value of i: {i}")

# Using a while loop
count = 0
while count < 5:
    print(f"Current count: {count}")
    count += 1

# Using a nested loop
for i in range(3):
    print(f"Outer loop, i: {i}")
    for j in range(2):
        print(f"  Inner loop, j: {j}")

decompiled

fruits = ('apple', 'banana', 'orange', 'grape')
for fruit in fruits:
    print('Current fruit: {}'.format(fruit))
for i in range(5):
    print('Current value of i: {}'.format(i))
count = 0
while count < 5:
    print('Current count: {}'.format(count))
    count += 1
for i in range(3):
    print('Outer loop, i: {}'.format(i))
    for j in range(2):
        print('  Inner loop, j: {}'.format(j))

List comprehensions

original

# Basic list comprehension
squares = [x**2 for x in range(1, 6)]
print(squares)  # Output: [1, 4, 9, 16, 25]

# List comprehension with a condition
even_squares = [x**2 for x in range(1, 6) if x % 2 == 0]
print(even_squares)  # Output: [4, 16]

# Nested list comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose = [[row[i] for row in matrix] for i in range(len(matrix))]
print(transpose)  # Output: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

decompiled

squares = [x**2 for x in range(1, 6)]
print(squares)

even_squares = [x**2 for x in range(1, 6) if x**2 % 2 == 0]
print(even_squares)

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose = [[row[i] for row in matrix] for i in range(len(matrix))]
print(transpose)

Functions

original

global_var = "I'm a global variable"

def outer_function():
    outer_local_var = "I'm a local variable in the outer function"

    def inner_function():
        nonlocal outer_local_var
        inner_local_var = "I'm a local variable in the inner function"
        print(f"Inner function: {inner_local_var}")
        print(f"Inner function: {outer_local_var}")
        print(f"Inner function: {global_var}")

    print(f"Outer function: {outer_local_var}")
    print(f"Outer function: {global_var}")

    inner_function()

def calculate(operation, a, b):
    if operation == "add":
        return a + b
    elif operation == "subtract":
        return a - b
    elif operation == "multiply":
        return a * b
    elif operation == "divide":
        return a / b
    else:
        return None

# Test the outer_function
outer_function()

# Test the calculate function
print(calculate("add", 4, 5))

# Lambda function example
multiply = lambda x, y: x * y
print(multiply(3, 4))

decompiled

global_var = "I'm a global variable"

def outer_function():
    outer_local_var = "I'm a local variable in the outer function"

    def inner_function():
        inner_local_var = "I'm a local variable in the inner function"
        print("Inner function: ", inner_local_var)
        print("Inner function: ", outer_local_var)
        print("Inner function: ", global_var)

    print("Outer function: ", outer_local_var)
    print("Outer function: ", global_var)
    inner_function()

def calculate(operation, a, b):
    if operation == 'add':
        return a + b
    elif operation == 'subtract':
        return a - b
    elif operation == 'multiply':
        return a * b
    elif operation == 'divide':
        return a / b
    else:
        return None

multiply = lambda x, y: x * y

print(calculate('add', 4, 5))
print(multiply(3, 4))

Classes and objects

original

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        print(f"{self.name} makes a generic animal sound.")

    def describe(self):
        print(f"{self.name} is {self.age} years old.")


class Dog(Animal):
    def __init__(self, name, age, breed):
        super().__init__(name, age)
        self.breed = breed

    def speak(self):
        print(f"{self.name} barks!")

    def describe_breed(self):
        print(f"{self.name} is a {self.breed}.")


class Cat(Animal):
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color

    def speak(self):
        print(f"{self.name} meows!")

    def describe_color(self):
        print(f"{self.name} has a {self.color} coat.")


# Creating objects
animal = Animal("Generic animal", 3)
dog = Dog("Buddy", 5, "Golden Retriever")
cat = Cat("Whiskers", 7, "black")

# Calling methods on objects
animal.speak()
animal.describe()

dog.speak()
dog.describe()
dog.describe_breed()

cat.speak()
cat.describe()
cat.describe_color()

decompiled

class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        print(f"{self.name} makes a generic animal sound.")

    def describe(self):
        print(f"{self.name} is {self.age} years old.")


class Dog(Animal):
    def __init__(self, name, age, breed):
        super().__init__(name, age)
        self.breed = breed

    def speak(self):
        print(f"{self.name} barks!")

    def describe_breed(self):
        print(f"{self.name} is a {self.breed}.")


class Cat(Animal):
    def __init__(self, name, age, color):
        super().__init__(name, age)
        self.color = color

    def speak(self):
        print(f"{self.name} meows!")

    def describe_color(self):
        print(f"{self.name} has a {self.color} coat.")


animal = Animal("Generic animal", 3)
dog = Dog("Buddy", 5, "Golden Retriever")
cat = Cat("Whiskers", 7, "black")

animal.speak()
animal.describe()

dog.speak()
dog.describe()
dog.describe_breed()

cat.speak()
cat.describe()
cat.describe_color()

Modules and packages

original

from animals.mammals import get_mammals, get_mammal_info

def main():
    mammals = get_mammals()
    print("Mammals:")
    for mammal in mammals:
        print(mammal)

    print("\nMammal info:")
    for mammal in mammals:
        print(get_mammal_info(mammal))

if __name__ == "__main__":
    main()

decompiled

from animals.mammals import get_mammals, get_mammal_info

def main():
    mammals = get_mammals()
    print('Mammals:')
    for mammal in mammals:
        print(mammal)
    print('\nMammal info:')
    for mammal in mammals:
        print(get_mammal_info(mammal))

if __name__ == '__main__':
    main()

Exception handling

original

def divide(a, b):
    try:
        result = a / b
        print(f"{a} divided by {b} is {result}")
    except ZeroDivisionError:
        print("Cannot divide by zero.")


divide(10, 2)
divide(10, 0)


def safe_conversion(value, to_int=True):
    try:
        if to_int:
            converted = int(value)
        else:
            converted = float(value)
        print(f"Converted {value} to {converted}")
    except ValueError:
        print(f"Invalid value: {value}")
    except TypeError:
        print(f"Unsupported type: {type(value).__name__}")


safe_conversion("42")
safe_conversion("3.14", False)
safe_conversion("abc")
safe_conversion(None)


def read_file(file_name):
    try:
        file = open(file_name, "r")
        content = file.read()
        print(f"File content:\n{content}")
    except FileNotFoundError:
        print("File not found.")
    finally:
        if "file" in locals() and not file.closed:
            file.close()
            print("File closed.")


read_file("example.txt")


class InvalidAgeError(ValueError):
    pass


def check_age(age):
    if age < 0:
        raise InvalidAgeError("Age cannot be negative.")
    elif age > 120:
        raise InvalidAgeError("Age is too high.")
    else:
        print("Age is valid.")


try:
    check_age(25)
    check_age(-5)
except InvalidAgeError as e:
    print(e)

decompiled

def divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print('Cannot divide by zero.')
    else:
        print(f'{a} divided by {b} is {result}')

def safe_conversion(value, to_int=True):
    try:
        if to_int:
            converted = int(value)
        else:
            converted = float(value)
    except ValueError:
        print(f'Invalid value: {value}')
    except TypeError:
        print(f'Unsupported type: {type(value).__name__}')
    else:
        print(f'Converted {value} to {converted}')

def read_file(file_name):
    try:
        file = open(file_name, 'r')
    except FileNotFoundError:
        print('File not found.')
    else:
        content = file.read()
        print(f'File content:\n{content}')
        try:
            locals()['file']
        except KeyError:
            pass
        else:
            if not file.closed:
                file.close()
                print('File closed.')
            raise

class InvalidAgeError(ValueError):
    pass

def check_age(age):
    if age < 0:
        raise InvalidAgeError('Age cannot be negative.')
    elif age > 120:
        raise InvalidAgeError('Age is too high.')
    else:
        print('Age is valid.')

File I/O

original

file_name = "example.txt"

with open(file_name, "r") as file:
    content = file.read()
    print(f"File content:\n{content}")
file_name = "output.txt"
content = "Hello, World!"

with open(file_name, "w") as file:
    file.write(content)
    print(f"Wrote content to {file_name}")
file_name = "log.txt"
log_entry = "This is a log entry."

with open(file_name, "a") as file:
    file.write(f"{log_entry}\n")
    print(f"Appended log entry to {file_name}")
file_name = "example.txt"

with open(file_name, "r") as file:
    print(f"Reading {file_name} line by line:")
    for line in file:
        print(line.strip())
import json

file_name = "data.json"
data = {"name": "John", "age": 30, "city": "New York"}

# Writing JSON data to a file
with open(file_name, "w") as file:
    json.dump(data, file)
    print(f"Wrote JSON data to {file_name}")

# Reading JSON data from a file
with open(file_name, "r") as file:
    loaded_data = json.load(file)
    print(f"Read JSON data from {file_name}:")
    print(loaded_data)

decompiled

file_name = 'example.txt'

with open(file_name, 'r') as file:
    content = file.read()

print('File content:\n{}'.format(content))

try:
    with open('output.txt', 'w') as file:
        content = 'Hello, World!'
        file.write(content)

    print('Wrote content to {}'.format(file_name))
except:
    pass

try:
    with open('log.txt', 'a') as file:
        log_entry = 'This is a log entry.'
        file.write('{}\n'.format(log_entry))

    print('Appended log entry to {}'.format(file_name))
except:
    pass

file_name = 'example.txt'

print('Reading {} line by line:'.format(file_name))
with open(file_name, 'r') as file:
    for line in file:
        print(line.strip())

import json

file_name = 'data.json'
data = {'name': 'John', 'age': 30, 'city': 'New York'}

with open(file_name, 'w') as file:
    json.dump(data, file)

print('Wrote JSON data to {}'.format(file_name))

with open(file_name, 'r') as file:
    loaded_data = json.load(file)

print('Read JSON data from {}:'.format(file_name))
print(loaded_data)

Standard library

original

import os

# Get the current working directory
cwd = os.getcwd()
print(f"Current working directory: {cwd}")

# List files and directories in the current directory
print("Files and directories in the current directory:")
for item in os.listdir(cwd):
    print(item)

# Create a new directory
new_dir = "example_directory"
os.makedirs(new_dir, exist_ok=True)
print(f"Created new directory: {new_dir}")

# Rename the directory
new_name = "renamed_directory"
os.rename(new_dir, new_name)
print(f"Renamed directory from {new_dir} to {new_name}")

# Remove the directory
os.rmdir(new_name)
print(f"Removed directory: {new_name}")
import shutil

src_file = "source.txt"
dst_file = "destination.txt"

# Copy a file
shutil.copy(src_file, dst_file)
print(f"Copied {src_file} to {dst_file}")

# Move a file
new_location = "moved.txt"
shutil.move(dst_file, new_location)
print(f"Moved {dst_file} to {new_location}")

# Remove a file
os.remove(new_location)
print(f"Removed file: {new_location}")
import glob

# Find all Python files in the current directory
print("Python files in the current directory:")
for py_file in glob.glob("*.py"):
    print(py_file)
import tempfile

# Create a temporary file and write content to it
with tempfile.NamedTemporaryFile(mode="w+t", delete=False) as temp_file:
    temp_file.write("Hello, World!")
    temp_path = temp_file.name
    print(f"Created temporary file: {temp_path}")

# Read the content of the temporary file
with open(temp_path, "r") as temp_file:
    content = temp_file.read()
    print(f"Content of the temporary file: {content}")

# Remove the temporary file
os.remove(temp_path)
print(f"Removed temporary file: {temp_path}")

decompiled

import os
import shutil
import glob
import tempfile

cwd = os.getcwd()
print('Current working directory: {0}'.format(cwd))

print('Files and directories in the current directory:')
for item in os.listdir(cwd):
    print(item)

new_dir = 'example_directory'
os.makedirs(new_dir, exist_ok=True)
print('Created new directory: {0}'.format(new_dir))

new_name = 'renamed_directory'
os.rename(new_dir, new_name)
print('Renamed directory from {0} to {1}'.format(new_dir, new_name))

os.rmdir(new_name)
print('Removed directory: {0}'.format(new_name))

src_file = 'source.txt'
dst_file = 'destination.txt'
shutil.copy(src_file, dst_file)
print('Copied {0} to {1}'.format(src_file, dst_file))

new_location = 'moved.txt'
shutil.move(dst_file, new_location)
print('Moved {0} to {1}'.format(dst_file, new_location))

os.remove(new_location)
print('Removed file: {0}'.format(new_location))

print('Python files in the current directory:')
for py_file in glob.glob('*.py'):
    print(py_file)

with tempfile.NamedTemporaryFile('w+t', delete=False) as temp_file:
    temp_file.write('Hello, World!')
    temp_path = temp_file.name
    print('Created temporary file: {0}'.format(temp_path))

with open(temp_path, 'r') as temp_file:
    content = temp_file.read()
    print('Content of the temporary file: {0}'.format(content))

os.remove(temp_path)
print('Removed temporary file: {0}'.format(temp_path))

Development

Setup

poetry install
poetry run pre-commit install

Set OPENAI_API_KEY environment variable. If you're using direnv, you can use .envrc.template as a template. Put src/pychd/logging.conf. You can copy src/pychd/logging.conf.template like this:

cp src/pychd/logging.conf.template src/pychd/logging.conf

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pychd-0.1.6.tar.gz (12.6 kB view hashes)

Uploaded Source

Built Distribution

pychd-0.1.6-py3-none-any.whl (9.7 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page