Code_editor / utils.py
vsj0702's picture
Added import random
a7a9c2f verified
raw
history blame
5.57 kB
import sys
import random
import os
import subprocess
from io import StringIO
import contextlib
import tempfile
import requests
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_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"]]
first_key = random.choice(keys)
result = _call_onecompiler_api(first_key, code, stdin, language, filename)
if _is_quota_or_invalid(result):
# Fallback: try all keys one-by-one until one works
for key in keys:
if key == first_key:
continue # Already tried this one
result = _call_onecompiler_api(key, code, stdin, language, filename)
if not _is_quota_or_invalid(result):
return result
return result # Either success, or last failed response
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
return any(token in error.lower() for token in ["quota", "e002", "e003", "invalid", "exhausted"])
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)
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 export_session(code: str, output: str, error: str) -> dict:
return {
"timestamp": datetime.now().isoformat(),
"code": code,
"output": output,
"error": error
}