summaryrefslogtreecommitdiff
path: root/yaksh/scilab_code_evaluator.py
blob: fedfab3bbd162661d4f79e2baf80eff8548e7c95 (plain)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python
import traceback
import os
from os.path import join, isfile
import subprocess
import re
import importlib

# local imports
from code_evaluator import CodeEvaluator


class ScilabCodeEvaluator(CodeEvaluator):
    """Tests the Scilab code obtained from Code Server"""
    # def __init__(self, test_case_data, test, language, user_answer,
    #                  ref_code_path=None, in_dir=None):
    #     super(ScilabCodeEvaluator, self).__init__(test_case_data, test,
    #                                              language, user_answer,
    #                                              ref_code_path, in_dir)

    #     # Removes all the commands that terminates scilab
    #     self.user_answer, self.terminate_commands = self._remove_scilab_exit(user_answer.lstrip())
    #     self.test_case_args = self.setup()

    def setup(self):
        super(ScilabCodeEvaluator, self).setup()
        # ref_path, test_case_path = self._set_test_code_file_path(self.ref_code_path)
        self.submit_code_path = self.create_submit_code_file('function.sci')
        # return ref_path, # Return as a tuple

    def teardown(self):
        super(ScilabCodeEvaluator, self).teardown()
        # Delete the created file.
        os.remove(self.submit_code_path)

    # def compile_code(self, user_answer, test_case):
    #     if hasattr(self, 'compiled_output'):
    #         return None
    #     else:
    #         ref_code_path = test_case
    #         clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path)
    #         user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip())

    #         self.write_to_submit_code_file(self.submit_code_path, user_answer)
    #         # Throw message if there are commmands that terminates scilab
    #         self.add_err = ""
    #         if terminate_commands:
    #             self.add_err = "Please do not use exit, quit and abort commands in your\
    #                         code.\n Otherwise your code will not be evaluated\
    #                         correctly.\n"

    #         cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path)
    #         cmd += ' | timeout 8 scilab-cli -nb'
    #         self.compiled_output = self._run_command(cmd,
    #                                 shell=True,
    #                                 stdout=subprocess.PIPE,
    #                                 stderr=subprocess.PIPE)
    #         return self.compiled_output

    def check_code(self, user_answer, test_case):
        ref_code_path = test_case
        clean_ref_path, clean_test_case_path = self._set_test_code_file_path(ref_code_path)
        user_answer, terminate_commands = self._remove_scilab_exit(user_answer.lstrip())

        success = False
        self.write_to_submit_code_file(self.submit_code_path, user_answer)
        # Throw message if there are commmands that terminates scilab
        add_err = ""
        if terminate_commands:
            add_err = "Please do not use exit, quit and abort commands in your\
                        code.\n Otherwise your code will not be evaluated\
                        correctly.\n"

        cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(clean_ref_path)
        cmd += ' | timeout 8 scilab-cli -nb'
        ret = self._run_command(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        # success = False
        # proc, stdout, stderr = self.compiled_output
        proc, stdout, stderr = ret 

        # Get only the error.
        stderr = self._get_error(stdout)
        if stderr is None:
            # Clean output
            stdout = self._strip_output(stdout)
            if proc.returncode == 5:
                success, err = True, "Correct answer"
            else:
                # err = self.add_err + stdout
                err = add_err + stdout
        else:
            # err = self.add_err + stderr
            err = add_err + stderr

        return success, err

    # def check_code(self, ref_path):
    #     success = False

    #     # Throw message if there are commmands that terminates scilab
    #     add_err=""
    #     if self.terminate_commands:
    #         add_err = "Please do not use exit, quit and abort commands in your\
    #                     code.\n Otherwise your code will not be evaluated\
    #                     correctly.\n"

    #     cmd = 'printf "lines(0)\nexec(\'{0}\',2);\nquit();"'.format(ref_path)
    #     cmd += ' | timeout 8 scilab-cli -nb'
    #     ret = self._run_command(cmd,
    #                             shell=True,
    #                             stdout=subprocess.PIPE,
    #                             stderr=subprocess.PIPE)
    #     proc, stdout, stderr = ret

    #     # Get only the error.
    #     stderr = self._get_error(stdout)
    #     if stderr is None:
    #         # Clean output
    #         stdout = self._strip_output(stdout)
    #         if proc.returncode == 5:
    #             success, err = True, "Correct answer"
    #         else:
    #             err = add_err + stdout
    #     else:
    #         err = add_err + stderr

    #     return success, err

    def _remove_scilab_exit(self, string):
        """
            Removes exit, quit and abort from the scilab code
        """
        new_string = ""
        terminate_commands = False
        for line in string.splitlines():
            new_line = re.sub(r"exit.*$", "", line)
            new_line = re.sub(r"quit.*$", "", new_line)
            new_line = re.sub(r"abort.*$", "", new_line)
            if line != new_line:
                terminate_commands = True
            new_string = new_string + '\n' + new_line
        return new_string, terminate_commands

    def _get_error(self, string):
        """
            Fetches only the error from the string.
            Returns None if no error.
        """
        obj = re.search("!.+\n.+", string)
        if obj:
            return obj.group()
        return None

    def _strip_output(self, out):
        """
            Cleans whitespace from the output
        """
        strip_out = "Message"
        for l in out.split('\n'):
            if l.strip():
                strip_out = strip_out+"\n"+l.strip()
        return strip_out