diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afd722b..9ae99c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,26 +1,30 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: + branches: + - main jobs: - ci: - strategy: - fail-fast: false - matrix: - python-version: ["3.8", "3.9", "3.10"] - os: [ubuntu-latest] - runs-on: ${{ matrix.os }} + lint: + name: lint + runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v3 - - name: Install poetry - run: pipx install poetry - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: "poetry" - - name: Install - run: | - poetry install - poetry run pre-commit install - - name: Lint + - uses: actions/checkout@v4 + + - name: Install Rye run: | - poetry run pre-commit run --files .pre-commit-config.yaml + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: 0.24.0 + RYE_INSTALL_OPTION: "--yes" + + - name: Install dependencies + run: rye sync --all-features + + - name: Run lints + run: pre-commit diff --git a/bin/publish-pypi b/bin/publish-pypi old mode 100644 new mode 100755 diff --git a/example/decompiled/01_decompiled_example_variables.py b/example/decompiled/01_decompiled_example_variables.py index 8691005..0c085a9 100644 --- a/example/decompiled/01_decompiled_example_variables.py +++ b/example/decompiled/01_decompiled_example_variables.py @@ -1,11 +1,11 @@ -name = 'John Doe' +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') \ No newline at end of file +print("Name:", name) +print("Age:", age) +print("Height:", height, "feet") +print("Age next year:", age_next_year) +print("Half height:", half_height, "feet") diff --git a/example/decompiled/02_decompiled_example_data_types.py b/example/decompiled/02_decompiled_example_data_types.py index d3a333f..822da16 100644 --- a/example/decompiled/02_decompiled_example_data_types.py +++ b/example/decompiled/02_decompiled_example_data_types.py @@ -1,17 +1,17 @@ integer_example = 42 float_example = 3.14 -string_example = 'Hello, World!' +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'} +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) \ No newline at end of file +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) diff --git a/example/decompiled/03_decompiled_example_if_else.py b/example/decompiled/03_decompiled_example_if_else.py index 0e08f3d..062413c 100644 --- a/example/decompiled/03_decompiled_example_if_else.py +++ b/example/decompiled/03_decompiled_example_if_else.py @@ -1,19 +1,19 @@ age = 25 -country = 'USA' -job_status = 'employed' -favorite_color = 'blue' +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.') +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.') + 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.') + 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.') + if country != "USA" or favorite_color != "blue": + print("Not minor, not USA + blue, unemployed.") else: - print('Not minor, not USA + blue, other status.') \ No newline at end of file + print("Not minor, not USA + blue, other status.") diff --git a/example/decompiled/04_decompiled_example_loops.py b/example/decompiled/04_decompiled_example_loops.py index fcb4be1..6203672 100644 --- a/example/decompiled/04_decompiled_example_loops.py +++ b/example/decompiled/04_decompiled_example_loops.py @@ -1,13 +1,13 @@ -fruits = ('apple', 'banana', 'orange', 'grape') +fruits = ("apple", "banana", "orange", "grape") for fruit in fruits: - print('Current fruit: {}'.format(fruit)) + print("Current fruit: {}".format(fruit)) for i in range(5): - print('Current value of i: {}'.format(i)) + print("Current value of i: {}".format(i)) count = 0 while count < 5: - print('Current count: {}'.format(count)) + print("Current count: {}".format(count)) count += 1 for i in range(3): - print('Outer loop, i: {}'.format(i)) + print("Outer loop, i: {}".format(i)) for j in range(2): - print(' Inner loop, j: {}'.format(j)) \ No newline at end of file + print(" Inner loop, j: {}".format(j)) diff --git a/example/decompiled/05_decompiled_example_list_comprehensions.py b/example/decompiled/05_decompiled_example_list_comprehensions.py index e01ab9e..fca28d0 100644 --- a/example/decompiled/05_decompiled_example_list_comprehensions.py +++ b/example/decompiled/05_decompiled_example_list_comprehensions.py @@ -6,4 +6,4 @@ 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) \ No newline at end of file +print(transpose) diff --git a/example/decompiled/06_decompiled_example_functions.py b/example/decompiled/06_decompiled_example_functions.py index 2f8845a..ea2bf92 100644 --- a/example/decompiled/06_decompiled_example_functions.py +++ b/example/decompiled/06_decompiled_example_functions.py @@ -1,5 +1,6 @@ global_var = "I'm a global variable" + def outer_function(): outer_local_var = "I'm a local variable in the outer function" @@ -13,19 +14,21 @@ def inner_function(): print("Outer function: ", global_var) inner_function() + def calculate(operation, a, b): - if operation == 'add': + if operation == "add": return a + b - elif operation == 'subtract': + elif operation == "subtract": return a - b - elif operation == 'multiply': + elif operation == "multiply": return a * b - elif operation == 'divide': + elif operation == "divide": return a / b else: return None + multiply = lambda x, y: x * y -print(calculate('add', 4, 5)) -print(multiply(3, 4)) \ No newline at end of file +print(calculate("add", 4, 5)) +print(multiply(3, 4)) diff --git a/example/decompiled/07_decompiled_example_classes_objects.py b/example/decompiled/07_decompiled_example_classes_objects.py index 35786ac..eb232ed 100644 --- a/example/decompiled/07_decompiled_example_classes_objects.py +++ b/example/decompiled/07_decompiled_example_classes_objects.py @@ -47,4 +47,4 @@ def describe_color(self): cat.speak() cat.describe() -cat.describe_color() \ No newline at end of file +cat.describe_color() diff --git a/example/decompiled/08_decompiled_example_modules_packages.py b/example/decompiled/08_decompiled_example_modules_packages.py index 6f63acb..891c38c 100644 --- a/example/decompiled/08_decompiled_example_modules_packages.py +++ b/example/decompiled/08_decompiled_example_modules_packages.py @@ -1,13 +1,15 @@ from animals.mammals import get_mammals, get_mammal_info + def main(): mammals = get_mammals() - print('Mammals:') + print("Mammals:") for mammal in mammals: print(mammal) - print('\nMammal info:') + print("\nMammal info:") for mammal in mammals: print(get_mammal_info(mammal)) -if __name__ == '__main__': - main() \ No newline at end of file + +if __name__ == "__main__": + main() diff --git a/example/decompiled/09_decompiled_example_exceptioins.py b/example/decompiled/09_decompiled_example_exceptioins.py index 01535d0..7efab2f 100644 --- a/example/decompiled/09_decompiled_example_exceptioins.py +++ b/example/decompiled/09_decompiled_example_exceptioins.py @@ -2,9 +2,10 @@ def divide(a, b): try: result = a / b except ZeroDivisionError: - print('Cannot divide by zero.') + print("Cannot divide by zero.") else: - print(f'{a} divided by {b} is {result}') + print(f"{a} divided by {b} is {result}") + def safe_conversion(value, to_int=True): try: @@ -13,37 +14,40 @@ def safe_conversion(value, to_int=True): else: converted = float(value) except ValueError: - print(f'Invalid value: {value}') + print(f"Invalid value: {value}") except TypeError: - print(f'Unsupported type: {type(value).__name__}') + print(f"Unsupported type: {type(value).__name__}") else: - print(f'Converted {value} to {converted}') + print(f"Converted {value} to {converted}") + def read_file(file_name): try: - file = open(file_name, 'r') + file = open(file_name, "r") except FileNotFoundError: - print('File not found.') + print("File not found.") else: content = file.read() - print(f'File content:\n{content}') + print(f"File content:\n{content}") try: - locals()['file'] + locals()["file"] except KeyError: pass else: if not file.closed: file.close() - print('File closed.') + print("File closed.") raise + class InvalidAgeError(ValueError): pass + def check_age(age): if age < 0: - raise InvalidAgeError('Age cannot be negative.') + raise InvalidAgeError("Age cannot be negative.") elif age > 120: - raise InvalidAgeError('Age is too high.') + raise InvalidAgeError("Age is too high.") else: - print('Age is valid.') \ No newline at end of file + print("Age is valid.") diff --git a/example/decompiled/10_decompiled_example_file_io.py b/example/decompiled/10_decompiled_example_file_io.py index cc86508..95697fb 100644 --- a/example/decompiled/10_decompiled_example_file_io.py +++ b/example/decompiled/10_decompiled_example_file_io.py @@ -1,47 +1,47 @@ -file_name = 'example.txt' +file_name = "example.txt" -with open(file_name, 'r') as file: +with open(file_name, "r") as file: content = file.read() -print('File content:\n{}'.format(content)) +print("File content:\n{}".format(content)) try: - with open('output.txt', 'w') as file: - content = 'Hello, World!' + with open("output.txt", "w") as file: + content = "Hello, World!" file.write(content) - print('Wrote content to {}'.format(file_name)) + 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)) + 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)) + print("Appended log entry to {}".format(file_name)) except: pass -file_name = 'example.txt' +file_name = "example.txt" -print('Reading {} line by line:'.format(file_name)) -with open(file_name, 'r') as file: +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'} +file_name = "data.json" +data = {"name": "John", "age": 30, "city": "New York"} -with open(file_name, 'w') as file: +with open(file_name, "w") as file: json.dump(data, file) -print('Wrote JSON data to {}'.format(file_name)) +print("Wrote JSON data to {}".format(file_name)) -with open(file_name, 'r') as file: +with open(file_name, "r") as file: loaded_data = json.load(file) -print('Read JSON data from {}:'.format(file_name)) -print(loaded_data) \ No newline at end of file +print("Read JSON data from {}:".format(file_name)) +print(loaded_data) diff --git a/example/decompiled/11_decompiled_example_std_library.py b/example/decompiled/11_decompiled_example_std_library.py index a6ffeaf..0bbacf4 100644 --- a/example/decompiled/11_decompiled_example_std_library.py +++ b/example/decompiled/11_decompiled_example_std_library.py @@ -4,47 +4,47 @@ import tempfile cwd = os.getcwd() -print('Current working directory: {0}'.format(cwd)) +print("Current working directory: {0}".format(cwd)) -print('Files and directories in the current directory:') +print("Files and directories in the current directory:") for item in os.listdir(cwd): print(item) -new_dir = 'example_directory' +new_dir = "example_directory" os.makedirs(new_dir, exist_ok=True) -print('Created new directory: {0}'.format(new_dir)) +print("Created new directory: {0}".format(new_dir)) -new_name = 'renamed_directory' +new_name = "renamed_directory" os.rename(new_dir, new_name) -print('Renamed directory from {0} to {1}'.format(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)) +print("Removed directory: {0}".format(new_name)) -src_file = 'source.txt' -dst_file = 'destination.txt' +src_file = "source.txt" +dst_file = "destination.txt" shutil.copy(src_file, dst_file) -print('Copied {0} to {1}'.format(src_file, dst_file)) +print("Copied {0} to {1}".format(src_file, dst_file)) -new_location = 'moved.txt' +new_location = "moved.txt" shutil.move(dst_file, new_location) -print('Moved {0} to {1}'.format(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("Removed file: {0}".format(new_location)) -print('Python files in the current directory:') -for py_file in glob.glob('*.py'): +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!') +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)) + print("Created temporary file: {0}".format(temp_path)) -with open(temp_path, 'r') as temp_file: +with open(temp_path, "r") as temp_file: content = temp_file.read() - print('Content of the temporary file: {0}'.format(content)) + print("Content of the temporary file: {0}".format(content)) os.remove(temp_path) -print('Removed temporary file: {0}'.format(temp_path)) \ No newline at end of file +print("Removed temporary file: {0}".format(temp_path)) diff --git a/example/python/02_example_data_types.py b/example/python/02_example_data_types.py index 69bcb41..7813405 100644 --- a/example/python/02_example_data_types.py +++ b/example/python/02_example_data_types.py @@ -14,11 +14,7 @@ tuple_example = (1, "apple", 3.14) # Dictionary -dict_example = { - "name": "John Doe", - "age": 30, - "city": "New York" -} +dict_example = {"name": "John Doe", "age": 30, "city": "New York"} # Set set_example = {1, 2, 3, 4, 5} diff --git a/example/python/06_example_functions.py b/example/python/06_example_functions.py index 6ca603c..bb4db69 100644 --- a/example/python/06_example_functions.py +++ b/example/python/06_example_functions.py @@ -1,5 +1,6 @@ global_var = "I'm a global variable" + def outer_function(): outer_local_var = "I'm a local variable in the outer function" @@ -15,6 +16,7 @@ def inner_function(): inner_function() + def calculate(operation, a, b): if operation == "add": return a + b @@ -27,6 +29,7 @@ def calculate(operation, a, b): else: return None + # Test the outer_function outer_function() diff --git a/example/python/08_example_modules_packages.py b/example/python/08_example_modules_packages.py index 6b13451..95ab4e6 100644 --- a/example/python/08_example_modules_packages.py +++ b/example/python/08_example_modules_packages.py @@ -1,5 +1,6 @@ from animals.mammals import get_mammals, get_mammal_info + def main(): mammals = get_mammals() print("Mammals:") @@ -10,5 +11,6 @@ def main(): for mammal in mammals: print(get_mammal_info(mammal)) + if __name__ == "__main__": main() diff --git a/pyproject.toml b/pyproject.toml index 95f13de..4bf2880 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,8 @@ [project] name = "pychd" -version = "0.1.0" -description = "Add your description here" +version = "0.2.0" +description = "The ChatGPT-powered decompiler for Python, providing superior code analysis capabilities" +readme = "README.md" authors = [ { name = "卍diohabara卍", email = "diohabara@users.noreply.github.com" } ] @@ -9,19 +10,24 @@ dependencies = [ "openai>=1.35.3", "xdis>=6.1.0", ] -readme = "README.md" requires-python = ">= 3.12" -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +[project.scripts] +openai = "pychd.cli:main" [tool.rye] managed = true -dev-dependencies = [] +# version pins are in requirements-dev.lock +dev-dependencies = [ + "pyright>=1.1.359", + "mypy", + "respx", + "pytest", + "ruff", +] [tool.hatch.metadata] allow-direct-references = true [tool.hatch.build.targets.wheel] -packages = ["src/pychd"] +packages = ["ychd"] diff --git a/requirements-dev.lock b/requirements-dev.lock index 39c9b0e..9faf83b 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -9,48 +9,36 @@ # generate-hashes: false -e file:. -annotated-types==0.7.0 - # via pydantic -anyio==4.4.0 - # via httpx - # via openai -certifi==2024.6.2 - # via httpcore - # via httpx +black==24.4.2 +cfgv==3.4.0 + # via pre-commit click==8.1.7 - # via xdis -distro==1.9.0 - # via openai -h11==0.14.0 - # via httpcore -httpcore==1.0.5 - # via httpx -httpx==0.27.0 - # via openai -idna==3.7 - # via anyio - # via httpx -openai==1.35.3 - # via pychd -pydantic==2.7.4 - # via openai -pydantic-core==2.18.4 - # via pydantic -pygments==2.18.0 - # via xdis -six==1.16.0 - # via xdis -sniffio==1.3.1 - # via anyio - # via httpx - # via openai -term-background==1.0.1 - # via xdis -tqdm==4.66.4 - # via openai + # via black +distlib==0.3.8 + # via virtualenv +filelock==3.15.4 + # via virtualenv +identify==2.5.36 + # via pre-commit +isort==5.13.2 +mypy==1.10.0 +mypy-extensions==1.0.0 + # via black + # via mypy +nodeenv==1.9.1 + # via pre-commit +packaging==24.1 + # via black +pathspec==0.12.1 + # via black +platformdirs==4.2.2 + # via black + # via virtualenv +pre-commit==3.7.1 +pyyaml==6.0.1 + # via pre-commit +ruff==0.4.10 typing-extensions==4.12.2 - # via openai - # via pydantic - # via pydantic-core -xdis==6.1.0 - # via pychd + # via mypy +virtualenv==20.26.3 + # via pre-commit diff --git a/requirements.lock b/requirements.lock index 39c9b0e..cf03c37 100644 --- a/requirements.lock +++ b/requirements.lock @@ -9,48 +9,3 @@ # generate-hashes: false -e file:. -annotated-types==0.7.0 - # via pydantic -anyio==4.4.0 - # via httpx - # via openai -certifi==2024.6.2 - # via httpcore - # via httpx -click==8.1.7 - # via xdis -distro==1.9.0 - # via openai -h11==0.14.0 - # via httpcore -httpcore==1.0.5 - # via httpx -httpx==0.27.0 - # via openai -idna==3.7 - # via anyio - # via httpx -openai==1.35.3 - # via pychd -pydantic==2.7.4 - # via openai -pydantic-core==2.18.4 - # via pydantic -pygments==2.18.0 - # via xdis -six==1.16.0 - # via xdis -sniffio==1.3.1 - # via anyio - # via httpx - # via openai -term-background==1.0.1 - # via xdis -tqdm==4.66.4 - # via openai -typing-extensions==4.12.2 - # via openai - # via pydantic - # via pydantic-core -xdis==6.1.0 - # via pychd