| import os | |
| import time | |
| from typing import Dict, Any | |
| import subprocess | |
| from flow_modules.aiflows.InterpreterFlowModule import InterpreterAtomicFlow | |
| class ExecuteCodeAtomicFlow(InterpreterAtomicFlow): | |
| """This class inherits from InterpreterAtomicFlow and is used to execute code in a file. | |
| It opens up the file in VSCode and waits for the user to save the file. Once the file is saved, it reads the code | |
| from the file and executes it. It then returns the output of the execution. | |
| *Input Interface*: | |
| - temp_code_file_location: The location of the file containing the code to be executed. | |
| - language: The language of the code to be executed. | |
| *Output Interface*: | |
| - interpreter_output: The output of the execution of the code. | |
| - code_ran: The code that was executed. | |
| *Configuration Parameters*: | |
| - `input_interface`: The input interface of the atomic flow. | |
| - `output_interface`: The output interface of the atomic flow. | |
| """ | |
| def _prepare_code(self, input_data: Dict[str, Any]): | |
| """ | |
| This method reads the code from the file and stores it in the input_data dictionary. | |
| :param input_data: The input_data dictionary. | |
| :type input_data: Dict[str, Any] | |
| :return: None | |
| """ | |
| file_location = input_data["temp_code_file_location"] | |
| start_marker = "# Code:\n" | |
| end_marker = "############" | |
| code_started = False | |
| code_str = "" | |
| with open(file_location, 'r') as file: | |
| for line in file: | |
| if line.strip() == start_marker.strip(): | |
| code_started = True | |
| continue | |
| if line.strip() == end_marker.strip(): | |
| break | |
| if code_started: | |
| code_str += line | |
| input_data["code"] = code_str | |
| def _check_input(self, input_data: Dict[str, Any]): | |
| """ | |
| This method checks if the input_data dictionary contains the required keys. | |
| :param input_data: The input_data dictionary. | |
| :type input_data: Dict[str, Any] | |
| :raises AssertionError: If the input_data dictionary does not contain the required keys. | |
| :return: None | |
| """ | |
| assert "temp_code_file_location" in input_data, "temp_code_file_location not passed to ExecuteCodeAtomicFlow" | |
| assert "language" in input_data, "language not passed to ExecuteCodeAtomicFlow" | |
| def _delete_file(self, file_location): | |
| """ | |
| This method deletes the file at the given location. | |
| :param file_location: The location of the file to be deleted. | |
| :type file_location: str | |
| :return: None | |
| """ | |
| if os.path.exists(file_location): | |
| os.remove(file_location) | |
| def _open_file_and_wait_for_upd(self, file_location): | |
| """ | |
| This method opens the file at the given location in VSCode and waits for the user to save the file. | |
| :param file_location: The location of the file to be opened. | |
| :type file_location: str | |
| :return: None | |
| """ | |
| process = subprocess.Popen(["code", "--wait", file_location]) | |
| while True: | |
| if process.poll() is not None: | |
| break | |
| time.sleep(1) | |
| def run( | |
| self, | |
| input_data: Dict[str, Any]): | |
| """ | |
| This method is called when the atomic flow is called. | |
| :param input_data: The input_data dictionary. | |
| :type input_data: Dict[str, Any] | |
| :return: The output of the execution of the code. | |
| :rtype: Dict[str, Any] | |
| """ | |
| self._check_input(input_data) | |
| file_loc = input_data["temp_code_file_location"] | |
| self._open_file_and_wait_for_upd(file_loc) | |
| self._prepare_code(input_data) | |
| self._process_input_data(input_data) | |
| execution_output = self._call() | |
| self._delete_file(file_loc) | |
| response = {"interpreter_output": execution_output, "code_ran": input_data['code']} | |
| return response | |