bpHigh commited on
Commit
63f5a9d
·
1 Parent(s): 506a87c

Add sandbox

Browse files
Files changed (1) hide show
  1. utils/code_sandbox.py +80 -0
utils/code_sandbox.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ast
2
+ import modal
3
+ import io
4
+ import sys
5
+
6
+ def detect_dependencies(code_snippet: str) -> list[str]:
7
+ tree = ast.parse(code_snippet)
8
+ imports = set()
9
+ for node in ast.walk(tree):
10
+ if isinstance(node, ast.Import):
11
+ for n in node.names:
12
+ imports.add(n.name.split('.')[0])
13
+ elif isinstance(node, ast.ImportFrom):
14
+ if node.module:
15
+ imports.add(node.module.split('.')[0])
16
+ imports = list(imports)
17
+ if 'sklearn' in imports:
18
+ imports[imports.index('sklearn')] = 'scikit-learn'
19
+ return imports
20
+
21
+
22
+ def build_sandbox(requirements: list[str], app: modal.App) -> tuple[modal.Sandbox, str]:
23
+ buffer = io.StringIO()
24
+ original_stdout = sys.stdout
25
+ sys.stdout = buffer
26
+ try:
27
+ with modal.enable_output():
28
+ image = modal.Image.debian_slim(python_version='3.10').pip_install(*requirements)
29
+ sandbox = modal.Sandbox.create(app=app, image=image, timeout=600, gpu="T4")
30
+ finally:
31
+ sys.stdout = original_stdout
32
+
33
+ logs = buffer.getvalue()
34
+ return sandbox, logs
35
+
36
+
37
+ def code_eval(code_snippet: str) -> tuple[dict, str]:
38
+ """
39
+ Run a python code snippet into a sandbox environment.
40
+
41
+ Args:
42
+ code_snippet (str): The Python code to execute.
43
+ Returns:
44
+ tuple[dict, str]:
45
+ - A dictionary containing execution results:
46
+ 'stdout', 'stderr', 'returncode', and 'error' (if any).
47
+ - A string with the image build logs (empty if no dependencies were detected).
48
+ """
49
+ try:
50
+ ast.parse(code_snippet)
51
+ except SyntaxError as e:
52
+ return {
53
+ "error": str(e),
54
+ "stdout": "",
55
+ "stderr": "",
56
+ "returncode": 1,
57
+ }, ""
58
+
59
+ app = modal.App.lookup("my-app", create_if_missing=True)
60
+ requirements = detect_dependencies(code_snippet)
61
+
62
+ if requirements:
63
+ sb, build_logs = build_sandbox(requirements, app)
64
+ else:
65
+ build_logs = ""
66
+ sb = modal.Sandbox.create(app=app, timeout=60)
67
+
68
+ with sb.open("/tmp/code.py", "w") as f:
69
+ f.write(code_snippet)
70
+
71
+ proc = sb.exec("python", "/tmp/code.py")
72
+ proc.wait()
73
+ error = proc.returncode != 0
74
+
75
+ return {
76
+ "error": "Script failed with non-zero exit code" if error else "",
77
+ "stdout": proc.stdout.read(),
78
+ "stderr": proc.stderr.read(),
79
+ "returncode": proc.returncode,
80
+ }, build_logs