Login
main >   my_ide >  


code_main.py

"""
This module is used to edit code.
"""

import argparse
import ast
import colorama
import os
import platform
import re
import shutil
import subprocess
import sys
import threading
import time

import autopep8
import openai
import pyflakes.api


colorama.init()


EDIT_PATH = os.path.join(os.getcwd(), "edit.py")
CODE_MAIN_PATH = os.path.join(os.getcwd(), "code_main.py")
EDIT_IN_PATH = os.path.join(os.getcwd(), "edit.txt")


def prep_files(code_main_path=CODE_MAIN_PATH, edit_path=EDIT_PATH, edit_in_path=EDIT_IN_PATH):
    """
    Creates two files, `edit_path` and `edit_in_path`, if they do not already exist. 
    The `edit_path` file is used to store code that the user types in during program execution, 
    while the `edit_in_path` file is used to store instructions for the user on what code to type.

    If `edit_path` or `edit_in_path` already exist, this function does not modify them in any way.

    Args:
        code_main_path (str): Path to the main code file. Defaults to `CODE_MAIN_PATH`.
        edit_path (str): Path to the file where user input code will be stored. Defaults to `EDIT_PATH`.
        edit_in_path (str): Path to the file where user input instructions will be stored. 
                            Defaults to `EDIT_IN_PATH`.
    """
    if not os.path.exists(edit_path):
        with open(edit_path, "w"):
            pass

    if not os.path.exists(edit_in_path):
        with open(edit_in_path, "w") as e:
            e.write("Write 'Hello World'.\n On exit, write 'Bye.'")


def print_function_code(code_string, func_name):
    """
    This function takes a string representation of Python code and the name of a target function within that code.
    It then uses the `ast` module to parse the code and extract the source code for the target function.
    Finally, it returns the extracted source code as a string.
    If the target function is not found within the code, the function returns None.
    """
    module_ast = ast.parse(code_string)
    for node in module_ast.body:
        if isinstance(node, ast.FunctionDef) and node.name == func_name:
            return ast.unparse(node)
            break
    return


def get_function_names(edit_in_path):
    """
    Given a path to a file containing Python code, returns a list of the function names in that code.
    """
    with open(edit_in_path, "r") as edit_input_file:
        edit_text = edit_input_file.read()
        function_names = re.findall(r"def\s+(\w+)\s*\(", edit_text)
        return function_names


def get_updates(code_main_path=CODE_MAIN_PATH, edit_in_path=EDIT_IN_PATH):
    """
    Prompts the user to enter some Python code, and generates text based on the input using the GPT language model.
    """
    with open(code_main_path, "r") as input_file:
        code_text = input_file.read()

    function_names = get_function_names(edit_in_path)

    if function_names:
        code_specified = ""
        for function_name in function_names:
            code_specified += "\n\n" + \
                print_function_code(code_text, function_name)
        code_text = code_specified
        print(f"{code_text}\nOnly using the above part of the script.")
    else:
        print("Using the whole script.")

    edit_text = ""
    with open(edit_in_path, "r") as edit_input_file:
        edit_text = edit_input_file.read()

    response_text = generate_text(code_text, edit_text)

    return response_text


def generate_text(code_text, edit_text):
    """
    This function is using gpt-3.5-turbo.
    """
    openai.api_key = "sk-"

    edit_request = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are an IDE who is a spiritual teacher."},
            {"role": "user", "content": "Here is my Python code."},
            {"role": "user", "content": code_text},
            {"role": "user", "content": edit_text},
        ]
    )

    return edit_request["choices"][0]["message"]["content"]


def load_meld(code_main_path=CODE_MAIN_PATH, edit_path=EDIT_PATH):
    """
    This function is used to load meld.
    """
    if platform.system() == "Windows":
        # Loading meld.
        os.system("meld " + code_main_path + " " + edit_path)
    else:
        subprocess.call(["meld", code_main_path, edit_path])


def close_meld():
    """
    This function is used to close meld.
    """
    if platform.system() == "Windows":
        os.system("taskkill /f /im Meld.exe")
        os.system("taskkill /f /im meld.exe")
        os.system("taskkill /f /im Meld")
        os.system("taskkill /f /im Code.exe")
    else:
        os.system("killall meld")


def load_edit(edit_path=EDIT_IN_PATH):
    """
    This function is used to load Code.
    """
    if platform.system() == "Windows":
        # Loading meld.
        os.system("Code " + edit_path)
    else:
        subprocess.call(["code", edit_path])


def close_edit():
    """
    This function is used to close Code.
    """
    if platform.system() == "Windows":
        os.system("taskkill /f /im Code.exe")
    else:
        os.system("killall code")


def lint_files(code_main_path=CODE_MAIN_PATH, edit_path=EDIT_PATH):
    """
    Lint a Python source code file by applying automated code formatting and checking for syntax errors using external libraries.

    :param code_main_path: str, the path to the main code file (default value is CODE_MAIN_PATH).
    :param edit_path: str, the path to a copy of the main code file that will be modified during the linting process (default value is EDIT_PATH).
    :return: str, an informative message about the linting success or failure.
    """
    shutil.copy(code_main_path, edit_path)
    # Format code according to PEP8
    with open(edit_path, "r+") as f:
        source_code = f.read()
        fixed_code = autopep8.fix_code(source_code)
        f.seek(0)
        f.write(fixed_code)
        f.truncate()

    # Check for errors using pyflakes
    with open(edit_path, 'r') as file:
        source = file.read()
        syntax_errors = pyflakes.api.check(source, file.name)
        if syntax_errors:
            print("Errors detected in {}: {}".format(code_main_path,
                                                     "\n".join([error.message for error in syntax_errors])))
        else:
            print("Lint Successful!")


def parse_args():
    """
    This function is used to parse arguments.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-c",
        "--close",
        help="Close all existing Meld.exe's before starting.",
        action="store_true",
    )

    parser.add_argument("-m", "--meld", help="Load Meld", action="store_true")

    parser.add_argument("-e", "--edit", help="Load Edit", action="store_true")

    parser.add_argument("-l", "--lint", help="Lint Files", action="store_true")

    args = parser.parse_args()

    return args


def main():
    """
    The main function is the entry point of the program. It serves 
    as the starting point for the execution of the code. The code 
    inside the main function will be executed first when the program 
    is run. 
    """
    print("Hello World")


def before_running():
    """
    This function creates a backup copy of the main code file before running it. 
    It creates a timestamp and appends it to a new file name where the backup is saved. 
    The backup is saved in a 'backups' folder in the current directory. 
    If the folder does not exist, it is created. 
    After the backup is saved, the function prints a message stating the name and location of the backup file. 
    """
    timestamp = time.strftime('%Y%m%d%H%M%S')

    # Create a backup file name with the timestamp
    backup_file_name = f'backups/code_main_backup_{timestamp}.py'
    os.makedirs(os.path.dirname(backup_file_name), exist_ok=True)

    # Copy the file to the backup file name
    shutil.copyfile('code_main.py', backup_file_name)

    # Print a message indicating that the backup was successful
    print(f'Backup created: {backup_file_name}')


if __name__ == "__main__":
    before_running()

    prep_files()

    args = parse_args()

    if args.close:
        close_edit()
        close_meld()
        time.sleep(1)

    if args.lint:
        lint_files()
        sys.exit()

    edit_text = get_updates()

    with open(EDIT_PATH, "w") as edit_file:
        edit_file.writelines(edit_text)

    if args.meld:
        thread = threading.Thread(target=load_meld, daemon=True)
        thread.start()

    if args.edit:
        thread = threading.Thread(target=load_edit, daemon=True)
        thread.start()

    main()
hidden1

hidden2