Spaces:
Running
Running
| import os | |
| import sys | |
| import random | |
| import tempfile | |
| import subprocess | |
| import requests | |
| from io import StringIO | |
| from datetime import datetime | |
| from typing import Tuple | |
| import contextlib | |
| # --- Utility context manager to capture stdout/stderr (for Python execution) --- | |
| def capture_output(): | |
| 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 | |
| # --- Public API to execute code --- | |
| def execute_code(code: str, stdin: str = "", language: str = "cpp") -> Tuple[str, str, str]: | |
| try: | |
| if language == "Python": | |
| return _execute_python(code, stdin) | |
| elif language == "C": | |
| return _execute_c(code, stdin) | |
| elif language == "C++": | |
| return _execute_cpp(code, stdin) | |
| elif language == "Java": | |
| return _execute_with_onecompiler(code, stdin, language="java", filename="Main.java") | |
| elif language == "JavaScript": | |
| return _execute_with_onecompiler(code, stdin, language="javascript", filename="script.js") | |
| elif language == "C#": | |
| return _execute_with_onecompiler(code, stdin, language="csharp", filename="Program.cs") | |
| else: | |
| return "", f"Unsupported language: {language}", None | |
| except Exception as e: | |
| return "", "", str(e) | |
| # --- Python Execution --- | |
| 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) | |
| # --- C Execution --- | |
| def _execute_c(code: str, stdin: str): | |
| return _compile_and_run(code, stdin, ext="c", compiler="gcc") | |
| # --- C++ Execution --- | |
| def _execute_cpp(code: str, stdin: str): | |
| return _compile_and_run(code, stdin, ext="cpp", compiler="g++") | |
| # --- Compilation helper --- | |
| def _compile_and_run(code: str, stdin: str, ext: str, compiler: str): | |
| with tempfile.TemporaryDirectory() as tmp: | |
| source = os.path.join(tmp, f"main.{ext}") | |
| binary = os.path.join(tmp, "main.out") | |
| with open(source, "w") as f: | |
| f.write(code) | |
| compile_cmd = [compiler, source, "-o", binary] | |
| comp_out, comp_err, comp_exc = _run_subprocess(compile_cmd) | |
| if comp_exc or comp_err: | |
| return comp_out, comp_err, comp_exc | |
| return _run_subprocess([binary], stdin) | |
| # --- Run subprocess and capture output --- | |
| 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) | |
| # --- Java, JS, C# via OneCompiler API --- | |
| def _execute_with_onecompiler(code: str, stdin: str, language: str, filename: str) -> Tuple[str, str, str]: | |
| keys = [os.environ["ONECOMPILER_API_KEY"], os.environ["ONECOMPILER_API_KEY1"]] | |
| primary_key = random.choice(keys) | |
| result = _call_onecompiler_api(primary_key, code, stdin, language, filename) | |
| if _is_quota_or_invalid(result): | |
| for key in keys: | |
| if key == primary_key: | |
| continue | |
| result = _call_onecompiler_api(key, code, stdin, language, filename) | |
| if not _is_quota_or_invalid(result): | |
| break | |
| return result | |
| def _call_onecompiler_api(key: str, code: str, stdin: str, language: str, filename: str) -> Tuple[str, str, str]: | |
| url = "https://onecompiler-apis.p.rapidapi.com/api/v1/run" | |
| headers = { | |
| "Content-Type": "application/json", | |
| "x-rapidapi-host": "onecompiler-apis.p.rapidapi.com", | |
| "x-rapidapi-key": key, | |
| } | |
| payload = { | |
| "language": language.lower(), | |
| "stdin": stdin, | |
| "files": [{"name": filename, "content": code}] | |
| } | |
| try: | |
| response = requests.post(url, json=payload, headers=headers, timeout=10) | |
| data = response.json() | |
| if data.get("status") == "failed": | |
| return "", "", f"OneCompiler Error: {data.get('error')}" | |
| return ( | |
| data.get("stdout", "").strip(), | |
| data.get("stderr", "") or "", | |
| data.get("exception", "") | |
| ) | |
| except Exception as e: | |
| return "", "", str(e) | |
| def _is_quota_or_invalid(result: Tuple[str, str, str]) -> bool: | |
| _, _, error = result | |
| if not error: | |
| return False | |
| error = error.lower() | |
| return any(term in error for term in ["quota", "e002", "e003", "invalid", "exhausted"]) | |
| # --- Export utility --- | |
| def export_session(code: str, output: str, error: str) -> dict: | |
| return { | |
| "timestamp": datetime.now().isoformat(), | |
| "code": code, | |
| "output": output, | |
| "error": error | |
| } | |