-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode_validator.py
More file actions
93 lines (69 loc) · 2.13 KB
/
code_validator.py
File metadata and controls
93 lines (69 loc) · 2.13 KB
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
import subprocess
import tempfile
import os
import shutil
class CodeValidator:
def __init__(self):
self.timeout = 2
self.python_exec = shutil.which("python") or shutil.which("python3")
self.node_available = shutil.which("node") is not None
def validate(self, language, code):
if not code:
return self._fail("empty code")
if language == "python":
return self._run_python(code)
if language == "javascript":
return self._run_node(code)
return self._fail("unsupported")
def _run_python(self, code):
path = None
try:
path = self._write(code, ".py")
r = subprocess.run(
[self.python_exec, path],
capture_output=True,
text=True,
timeout=self.timeout
)
return self._format(r)
except Exception as e:
return self._fail(str(e))
finally:
self._clean(path)
def _run_node(self, code):
if not self.node_available:
return self._fail("node missing")
path = None
try:
path = self._write(code, ".js")
r = subprocess.run(
["node", path],
capture_output=True,
text=True,
timeout=self.timeout
)
return self._format(r)
except Exception as e:
return self._fail(str(e))
finally:
self._clean(path)
def _write(self, code, ext):
f = tempfile.NamedTemporaryFile("w", suffix=ext, delete=False)
f.write(code)
f.close()
return f.name
def _clean(self, path):
if path and os.path.exists(path):
try:
os.remove(path)
except:
pass
def _format(self, r):
return {
"success": r.returncode == 0,
"stdout": r.stdout,
"stderr": r.stderr,
"returncode": r.returncode
}
def _fail(self, msg):
return {"success": False, "stderr": msg, "returncode": -1}