""" This module provides functions to extract and execute Python code from a string. The functions are: * extract_and_run_python_code(txt: str) -> str: Extracts and executes Python code from a string. * execute_code_with_timeout(code: str, timeout: int = 3) -> str: Executes Python code with a timeout and returns the output. Additional functions can be added as needed. """ import os import tempfile from subprocess import Popen, PIPE, TimeoutExpired def extract_and_run_python_code(txt: str) -> str: """ Extract and execute Python code from a provided string. Handles missing print statements for non-comment last lines, executes the code, and captures output or errors. Parameters: txt (str): Input string containing a possible Python code block. Returns: str: Execution result or error message wrapped in output formatting. """ def extract_code(input_str: str) -> str: """Extract Python code block delimited by ```python and ```.""" try: return input_str.split("```python", 1)[1].split("```", 1)[0].strip() except IndexError: raise ValueError("No valid Python code block found.") def ensure_print_statement(code: str) -> str: """ Append a print statement if the last line isn't a comment or a print statement. """ lines = code.splitlines() last_line = lines[-1].rstrip() if not last_line.startswith(("print(", "#", " ", "\t")) and (not ("return" in last_line)):# and len((last_line.split(" "))) == 1: lines[-1] = f"print({last_line})" return "\n".join(lines) if "```python" not in txt: return None # Return early if no Python code block is present try: # Extract and sanitize the code code_block = extract_code(txt) code_with_print = ensure_print_statement(code_block) # Execute the code and return output python_output = execute_code_with_timeout(code_with_print) # return f"PYTHON CODE OUTPUT:\n'''\n{python_output}\n'''" return f"Output of the Python code above:\n```\n{python_output}\n```" except Exception as error: return f"PYTHON CODE OUTPUT:\n```\nError: {str(error)}\n```" # Python code execution function with timeout # TODO (msuzgun): Improve the security of this function by using a sandboxed environment def execute_code_with_timeout(code: str, timeout: int = 3) -> str: """ Execute Python code with a timeout and return the output. Parameters: code (str): Python code to execute. timeout (int): Timeout duration in seconds. Returns: str: Captured output or error message from the code execution. """ with tempfile.NamedTemporaryFile( mode="w+t", suffix=".py", delete=False ) as temp_file: temp_file.write(code) temp_file.flush() try: # In case alias python=python3 is not set, use python3 instead of python process = Popen(["python3", temp_file.name], stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate(timeout=timeout) captured_output = stdout.decode().strip() error_output = stderr.decode().strip() if captured_output == "": if error_output != "": captured_output = f"Error in execution: {error_output}" else: captured_output = "(No output was generated. It is possible that you did not include a print statement in your code. If you want to see the output, please include a print statement.)" except TimeoutExpired: process.kill() captured_output = "Execution took too long, aborting..." finally: os.remove(temp_file.name) return captured_output