import io import sys import ast from logger import logger def run_code(code): """ Executes user-provided Python code and captures its output. Handles user input dynamically and detects defined functions. Parameters: code (str): Python code entered by the user. Returns: dict: Captured output and logged inputs. """ # Redirect stdout to capture code output old_stdout = sys.stdout redirected_output = sys.stdout = io.StringIO() # Create a dedicated execution namespace exec_globals = {} # Store user inputs input_log = [] # Custom input function to simulate input() behavior def custom_input(prompt=""): user_input = input(prompt) # Prompt the user dynamically input_log.append(user_input) return user_input # Add the custom input function to the execution namespace exec_globals["input"] = custom_input try: # Parse the code to detect function definitions tree = ast.parse(code) function_names = [ node.name for node in ast.walk(tree) if isinstance(node, ast.FunctionDef) ] # Execute the code in the dedicated namespace exec(code, exec_globals) # Check if functions are defined but not called captured_output = redirected_output.getvalue() if function_names: captured_output += f"\n\nDefined functions: {', '.join(function_names)}\n" captured_output += "Note: Functions need to be explicitly called to see their output." return {"output": captured_output, "inputs": input_log} except Exception as e: logger.error(f"Execution error: {e}") return {"output": f"Error: {e}", "inputs": input_log} finally: # Reset stdout sys.stdout = old_stdout