summaryrefslogtreecommitdiff
path: root/yaksh/tester/python/verifier.py
blob: 102dcb97f19488ea953bf5b12d5250dc678f082e (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
import sys
from .utils import import_by_path
from contextlib import contextmanager


@contextmanager
def redirect_stdout():
    from StringIO import StringIO
    new_target = StringIO()

    old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
    try:
        yield new_target # run some code with the replaced stdout
    finally:
        sys.stdout = old_target # restore to the previous value

# def redirect_stdout():
#     # import sys
#     from StringIO import StringIO
#     oldout,olderr = sys.stdout, sys.stderr
#     try:
#         out = StringIO()
#         err = StringIO()
#         # sys.stdout,sys.stderr = out, err
#         yield out, err
#     finally:
#         sys.stdout,sys.stderr = oldout, olderr
#         out = out.getvalue()
#         err = err.getvalue()

TESTER_BACKEND = {
    "python": "PythonPrintTesterBackend" #@@@rename to test-case-creator, this file should be backend.py
}

class TesterException(Exception):
    """ Parental class for all tester exceptions """
    pass

class UnknownBackendException(TesterException):
    """ Exception thrown if tester backend is not recognized. """
    pass


def detect_backend(language):
    """
    Detect the right backend for a test case.
    """
    backend_name = TESTER_BACKEND.get(language)
    # backend = import_by_path(backend_name)
    backend = PythonTesterBackend() #@@@
    return backend

class PythonPrintTesterBackend(object):
    def test_code(self, submitted, reference_output):
        """
        create a test command
        """
        with redirect_stdout() as output_buffer: 
            g = {}
            exec submitted in g

        # return_buffer = out.encode('string_escape')
        raw_output_value = output_buffer.getvalue()
        output_value = raw_output_value.encode('string_escape').strip()
        if output_value == str(reference_output):
            return True
        else:
            raise ValueError("Incorrect Answer", output_value, reference_output)


class PythonTesterBackend(object):
    # def __init__(self, test_case):
    #     self._test_case = test_case
    def create(self): #@@@ test()
        """
        create a test command
        """
        test_code = "assert {0}({1}) == {2}".format(self.test_case_parameters['function_name'], self.test_case_parameters['args'],
                                     self.test_case_parameters['expected_answer'])
        return test_code

    def pack(self, test_case):
        kw_args_dict = {}
        pos_args_list = []
        test_case_data = {}
        test_case_data['test_id'] = test_case.id
        test_case_data['func_name'] = test_case.func_name
        test_case_data['expected_answer'] = test_case.expected_answer

        if test_case.kw_args:
            for args in test_case.kw_args.split(","):
                arg_name, arg_value = args.split("=")
                kw_args_dict[arg_name.strip()] = arg_value.strip()

        if test_case.pos_args:
            for args in test_case.pos_args.split(","):
                pos_args_list.append(args.strip())

        test_case_data['kw_args'] = kw_args_dict
        test_case_data['pos_args'] = pos_args_list

        return test_case_data

    def unpack(self, test_case_data):
        pos_args = ", ".join(str(i) for i in test_case_data.get('pos_args')) \
                            if test_case_data.get('pos_args') else ""
        kw_args = ", ".join(str(k+"="+a) for k, a
                         in test_case_data.get('kw_args').iteritems()) \
                        if test_case_data.get('kw_args') else ""
        args = pos_args + ", " + kw_args if pos_args and kw_args \
                                            else pos_args or kw_args
        function_name = test_case_data.get('func_name')
        expected_answer = test_case_data.get('expected_answer')

        self.test_case_parameters = {
            'args': args,
            'function_name': function_name,
            'expected_answer': expected_answer
        }

        return self.test_case_parameters