File size: 4,932 Bytes
5d21581
c0e8d4b
 
5d21581
 
c0e8d4b
5d21581
c0e8d4b
5d21581
 
 
c0e8d4b
5d21581
 
 
 
 
 
 
 
c0e8d4b
5d21581
c0e8d4b
 
 
5d21581
c0e8d4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d21581
 
0f6a021
 
 
cfca35b
5d21581
 
 
 
c0e8d4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d21581
 
 
 
 
 
c0e8d4b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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
    }