import sys import os import subprocess from io import StringIO import contextlib import tempfile from datetime import datetime from typing import Tuple @contextlib.contextmanager def capture_output(): """Capture stdout and stderr for Python code""" stdout, stderr = StringIO(), StringIO() old_out, old_err = sys.stdout, sys.stderr try: sys.stdout, sys.stderr = stdout, stderr yield stdout, stderr finally: sys.stdout, sys.stderr = old_out, old_err def execute_code(code: str, stdin: str = "", language: str = "python") -> Tuple[str, str, str]: """ Execute code in the specified language and return (stdout, stderr, exception) Currently supports: python (default). Other languages scaffolded. """ try: if language == "python": return _execute_python(code, stdin) elif language == "c": return _execute_c(code, stdin) elif language == "cpp": return _execute_cpp(code, stdin) elif language == "java": return _execute_java(code, stdin) elif language == "js": return _execute_javascript(code, stdin) elif language == "csharp": return _execute_csharp(code, stdin) else: return "", f"Unsupported language: {language}", None except Exception as e: return "", "", str(e) def _execute_python(code: str, stdin: str) -> Tuple[str, str, str]: with capture_output() as (stdout, stderr): try: inputs = iter(stdin.splitlines()) input_override = lambda prompt='': next(inputs, '') local_vars = {"input": input_override} exec(code, {}, local_vars) return stdout.getvalue().strip(), stderr.getvalue().strip(), None except Exception as e: return stdout.getvalue().strip(), stderr.getvalue().strip(), str(e) def _run_subprocess(cmd, stdin_input=None) -> Tuple[str, str, str]: try: result = subprocess.run( cmd, input=stdin_input.encode() if stdin_input else None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=10 ) return result.stdout.decode(), result.stderr.decode(), None except Exception as e: return "", "", str(e) def _execute_c(code: str, stdin: str): with tempfile.TemporaryDirectory() as tmp: source_path = os.path.join(tmp, "main.c") binary_path = os.path.join(tmp, "main.out") with open(source_path, "w") as f: f.write(code) compile_cmd = ["gcc", source_path, "-o", binary_path] compile_out, compile_err, exc = _run_subprocess(compile_cmd) if exc or compile_err: return compile_out, compile_err, exc return _run_subprocess([binary_path], stdin) def _execute_cpp(code: str, stdin: str): with tempfile.TemporaryDirectory() as tmp: source_path = os.path.join(tmp, "main.cpp") binary_path = os.path.join(tmp, "main.out") with open(source_path, "w") as f: f.write(code) compile_cmd = ["g++", source_path, "-o", binary_path] compile_out, compile_err, exc = _run_subprocess(compile_cmd) if exc or compile_err: return compile_out, compile_err, exc return _run_subprocess([binary_path], stdin) def _execute_java(code: str, stdin: str): with tempfile.TemporaryDirectory() as tmp: class_name = "Main" source_path = os.path.join(tmp, f"{class_name}.java") with open(source_path, "w") as f: f.write(code) compile_cmd = ["javac", source_path] compile_out, compile_err, exc = _run_subprocess(compile_cmd) if exc or compile_err: return compile_out, compile_err, exc return _run_subprocess(["java", "-cp", tmp, class_name], stdin) def _execute_javascript(code: str, stdin: str): with tempfile.NamedTemporaryFile(suffix=".js", delete=False, mode="w") as f: f.write(code) temp_path = f.name try: return _run_subprocess(["node", temp_path], stdin) finally: os.remove(temp_path) def _execute_csharp(code: str, stdin: str): with tempfile.TemporaryDirectory() as tmp: source_path = os.path.join(tmp, "main.cs") binary_path = os.path.join(tmp, "main.exe") with open(source_path, "w") as f: f.write(code) compile_cmd = ["mcs", source_path, "-out:" + binary_path] compile_out, compile_err, exc = _run_subprocess(compile_cmd) if exc or compile_err: return compile_out, compile_err, exc return _run_subprocess(["mono", binary_path], stdin) def export_session(code: str, output: str, error: str) -> dict: return { "timestamp": datetime.now().isoformat(), "code": code, "output": output, "error": error }