62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
import subprocess
|
|
from pathlib import Path
|
|
|
|
# Maximum time (seconds) a subprocess is allowed to run before being killed.
|
|
RUN_TIMEOUT = 30
|
|
|
|
|
|
class ExecutionEngine:
|
|
"""Runs files from the editor in a subprocess and returns the output.
|
|
|
|
Currently supports Python (.py) and LaTeX (.tex) files.
|
|
Returns a dict with keys: stdout, stderr, rc (return code).
|
|
"""
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def run_code(self, active_file: Path) -> dict:
|
|
"""Execute the given file and return its output.
|
|
|
|
Args:
|
|
active_file: Absolute path to the file that should be run.
|
|
|
|
Returns:
|
|
{"stdout": str, "stderr": str, "rc": int}
|
|
rc == 0 means success, anything else is an error.
|
|
"""
|
|
suffix = active_file.suffix
|
|
current_dir = active_file.parent.resolve()
|
|
|
|
# Build the shell command depending on file type
|
|
if suffix == ".py":
|
|
cmd = ["py", active_file.name]
|
|
elif suffix == ".tex":
|
|
# pdflatex in non-interactive mode so it never waits for input
|
|
cmd = [
|
|
"pdflatex",
|
|
"-interaction=nonstopmode",
|
|
f"-output-directory={current_dir}",
|
|
active_file.name,
|
|
]
|
|
else:
|
|
return {"stdout": "", "stderr": f"Unsupported file type: {suffix}", "rc": 1}
|
|
|
|
try:
|
|
proc = subprocess.run(
|
|
cmd,
|
|
cwd=current_dir, # run inside the file's own directory
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=RUN_TIMEOUT,
|
|
)
|
|
return {"stdout": proc.stdout, "stderr": proc.stderr, "rc": proc.returncode}
|
|
|
|
except subprocess.TimeoutExpired:
|
|
return {"stdout": "", "stderr": f"Timed out after {RUN_TIMEOUT}s", "rc": -1}
|
|
except FileNotFoundError as e:
|
|
# Raised when the interpreter/compiler binary is not found on PATH
|
|
return {"stdout": "", "stderr": str(e), "rc": -1}
|
|
except Exception as e:
|
|
return {"stdout": "", "stderr": str(e), "rc": -1}
|