File size: 2,464 Bytes
63f5a9d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5d0386
63f5a9d
 
d5d0386
63f5a9d
 
c209a97
63f5a9d
 
 
 
 
 
 
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
import ast
import modal
import io
import sys

def detect_dependencies(code_snippet: str) -> list[str]:
    tree = ast.parse(code_snippet)
    imports = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for n in node.names:
                imports.add(n.name.split('.')[0])
        elif isinstance(node, ast.ImportFrom):
            if node.module:
                imports.add(node.module.split('.')[0])
    imports = list(imports)
    if 'sklearn' in imports:
        imports[imports.index('sklearn')] = 'scikit-learn'
    return imports


def build_sandbox(requirements: list[str], app: modal.App) -> tuple[modal.Sandbox, str]:
    buffer = io.StringIO()
    original_stdout = sys.stdout
    sys.stdout = buffer
    try:
        with modal.enable_output():
            image = modal.Image.debian_slim(python_version='3.10').pip_install(*requirements)
            sandbox = modal.Sandbox.create(app=app, image=image, timeout=600, gpu="T4")
    finally:
        sys.stdout = original_stdout

    logs = buffer.getvalue()
    return sandbox, logs


def code_eval(code_snippet: str) -> tuple[dict, str]:
    """
    Run a python code snippet into a sandbox environment.
    
    Args:
        code_snippet (str): The Python code to execute.
    Returns:
        tuple[dict, str]: 
            - A dictionary containing execution results:
                'stdout', 'stderr', 'returncode', and 'error' (if any).
            - A string with the image build logs (empty if no dependencies were detected).
    """
    try:
        ast.parse(code_snippet)
    except SyntaxError as e:
        return {
            "error": str(e),
            "stdout": "",
            "stderr": "",
            "returncode": 1,
        }, ""
    
    app = modal.App.lookup("my-app", create_if_missing=True)
    requirements = detect_dependencies(code_snippet)

    if requirements:
        sb, build_logs = build_sandbox(requirements, app)
    else:
        build_logs = ""
        sb = modal.Sandbox.create(app=app, timeout=60)

    with sb.open("/tmp/solution.py", "w") as f:
        f.write(code_snippet)

    proc = sb.exec("python", "/tmp/solution.py")
    proc.wait()
    error = proc.returncode != 0
    sb.terminate()

    return {
        "error": "Script failed with non-zero exit code" if error else "",
        "stdout": proc.stdout.read(),
        "stderr": proc.stderr.read(),
        "returncode": proc.returncode,
    }, build_logs