|
|
from fastapi import FastAPI, Request, Form |
|
|
from fastapi.responses import HTMLResponse |
|
|
from fastapi.templating import Jinja2Templates |
|
|
import sys |
|
|
import io |
|
|
|
|
|
app = FastAPI() |
|
|
templates = Jinja2Templates(directory="templates") |
|
|
|
|
|
|
|
|
def run_code_with_trace(code: str): |
|
|
trace_data = [] |
|
|
stdout_capture = io.StringIO() |
|
|
|
|
|
def tracer(frame, event, arg): |
|
|
if event == "line": |
|
|
trace_data.append({ |
|
|
"line": frame.f_lineno, |
|
|
"locals": frame.f_locals.copy() |
|
|
}) |
|
|
return tracer |
|
|
|
|
|
sys.settrace(tracer) |
|
|
try: |
|
|
exec(code, {}, {}) |
|
|
except Exception as e: |
|
|
trace_data.append({"error": str(e)}) |
|
|
finally: |
|
|
sys.settrace(None) |
|
|
|
|
|
output = stdout_capture.getvalue() |
|
|
stdout_capture.close() |
|
|
|
|
|
return trace_data, output |
|
|
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse) |
|
|
async def index(request: Request): |
|
|
return templates.TemplateResponse("index.html", {"request": request}) |
|
|
|
|
|
|
|
|
@app.post("/run", response_class=HTMLResponse) |
|
|
async def run_code(request: Request, code: str = Form(...)): |
|
|
trace, output = run_code_with_trace(code) |
|
|
return templates.TemplateResponse( |
|
|
"index.html", |
|
|
{ |
|
|
"request": request, |
|
|
"trace": trace, |
|
|
"output": output, |
|
|
"code": code |
|
|
} |
|
|
) |
|
|
|