File size: 1,668 Bytes
41e79e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from pathlib import Path
from src.safe_subprocess import run

def eval_script(path): 
    # Matlab has the requirement that all functions must appear at the end 
    # of the file. So we first have to write the call to the test-function at the 
    # beginning of the file.
    with open(path, 'r') as f:
        content = f.read()
    content = f"test();\n{content}"
    with open(path, 'w') as f:
        f.write(content)
    filename = path.stem 
    parent_dir = path.parent.absolute()

    # We use the matlab.engine to run the script; however, the way that the
    # matlab engine works requires that we call the script as if it were a 
    # member of the matlab.engine object. So we have to write a python script
    # that calls the matlab script. This also ensures that the script is called 
    # in a safe-subprocess. Who needs runtime reflection when you have IPC? 
    program= f"""
import matlab.engine
import io 
import sys
out = io.StringIO()
err = io.StringIO()
eng = matlab.engine.start_matlab()
eng.addpath(r'{parent_dir}',nargout=0)
try: 
    r = eng.{filename}(nargout=0, stdout=out,stderr=err)
    print(out.getvalue())
except matlab.engine.MatlabExecutionError as e:
    print(err.getvalue(), file=sys.stderr)
"""
    r = run(["python3", "-c", program], timeout_seconds=30)

    # This is still somewhat brittle.
    if r.timeout:
        status = "Timeout"
        exit_code = -1
    elif r.stderr == "":
        status = "OK"
        exit_code = 0
    else:
        status = "Exception"
        exit_code = 1

    return {
        "status": status,
        "exit_code": exit_code,
        "stdout": r.stdout,
        "stderr": r.stderr,
    }