Commit
·
621acf4
1
Parent(s):
b081fcb
Adding endpoint handler
Browse files- handler.py +63 -0
handler.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import pty
|
3 |
+
import subprocess
|
4 |
+
import select
|
5 |
+
import shlex
|
6 |
+
|
7 |
+
|
8 |
+
class EndpointHandler:
|
9 |
+
def __init__(self):
|
10 |
+
pass
|
11 |
+
|
12 |
+
def run_command(command):
|
13 |
+
def read_output(fd):
|
14 |
+
output = b""
|
15 |
+
while True:
|
16 |
+
r, _, _ = select.select([fd], [], [], 0.1)
|
17 |
+
if fd in r:
|
18 |
+
data = os.read(fd, 1024)
|
19 |
+
if not data:
|
20 |
+
break
|
21 |
+
output += data
|
22 |
+
else:
|
23 |
+
break
|
24 |
+
return output
|
25 |
+
|
26 |
+
master_fd, slave_fd = pty.openpty()
|
27 |
+
try:
|
28 |
+
process = subprocess.Popen(
|
29 |
+
shlex.split(command),
|
30 |
+
stdin=slave_fd,
|
31 |
+
stdout=slave_fd,
|
32 |
+
stderr=slave_fd,
|
33 |
+
text=True,
|
34 |
+
)
|
35 |
+
|
36 |
+
output = b""
|
37 |
+
while process.poll() is None:
|
38 |
+
output += read_output(master_fd)
|
39 |
+
|
40 |
+
# Capture any remaining output after the process has finished
|
41 |
+
output += read_output(master_fd)
|
42 |
+
|
43 |
+
process.wait()
|
44 |
+
finally:
|
45 |
+
os.close(master_fd)
|
46 |
+
os.close(slave_fd)
|
47 |
+
|
48 |
+
return output.decode()
|
49 |
+
|
50 |
+
def __call__(self, data):
|
51 |
+
"""
|
52 |
+
:param data: input data from the inference endpoint REST API
|
53 |
+
:return: output data
|
54 |
+
"""
|
55 |
+
# get inputs
|
56 |
+
command = data.pop("command", None)
|
57 |
+
if not isinstance(command, str):
|
58 |
+
return {"error": "command attribute is required"}
|
59 |
+
|
60 |
+
# run command
|
61 |
+
result = self.run_command(command)
|
62 |
+
|
63 |
+
return {"result": result}
|