~azzar1/unity/add-show-desktop-key

294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2008 The University of Melbourne
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18
# Module: parse_tute
19
# Author: Dilshan Angampitiya
20
# Date:   24/1/2008
21
22
"""
23
This file provides the function parse_tutorial_file which takes an
24
xml specification of a tutorial problem file and returns a test suite object
25
for that problem. It throws a ParseException if there was a problem parsing
26
the file.
27
"""
28
29
from xml.dom.minidom import *
30
from TestFramework import *
31
32
DEFAULT_TEST_TYPE = 'norm'
33
DEFAULT_CASE_TYPE = 'match'
34
35
class ParseException(Exception):
36
    " Error when parsing the xml problem file "
37
    def __init___(self, reason):
38
        self._reason = reason
39
40
    def __str__(self):
41
        return self._reason
42
43
def getTextData(element):
44
    """ Get the text and cdata inside an element
45
    Leading and trailing whitespace are stripped
46
    """
47
    data = ''
48
    for child in element.childNodes:
49
        if child.nodeType == child.CDATA_SECTION_NODE:
50
            data += child.data
51
        if child.nodeType == child.TEXT_NODE:
52
            data += child.data
53
54
    return data.strip()
55
56
def getCasePartData(partNode):
57
    """ Create an TestCasePaart instance from test part xml data
58
    """
59
    
60
    func_desc = partNode.getAttribute('desc')
495 by stevenbird
Fixes to permit content authors to produce nicer diagnostic responses as a result
61
    func_succeed = partNode.getAttribute('succeed')
62
    func_fail = partNode.getAttribute('fail')
63
    if not func_succeed:
64
        func_succeed = func_desc
65
    if not func_fail:
66
        func_fail = func_desc
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
67
    default = partNode.getAttribute('default')
68
    if default == '': default = DEFAULT_CASE_TYPE
69
    
495 by stevenbird
Fixes to permit content authors to produce nicer diagnostic responses as a result
70
    part = TestCasePart(func_succeed, func_fail, default)
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
71
72
    for child in partNode.childNodes:
73
        if child.nodeType != child.ELEMENT_NODE:
74
            continue
75
76
        if child.tagName == 'stdout':
77
            test_type = child.getAttribute('type')
78
            if test_type == '': test_type = DEFAULT_TEST_TYPE
79
            part.add_stdout_test(getTextData(child), test_type)
80
        elif child.tagName == 'stderr':
81
            test_type = child.getAttribute('type')
82
            if test_type == '': test_type = DEFAULT_TEST_TYPE
83
            part.add_stderr_test(getTextData(child), test_type)
299 by dilshan_a
Test framework now handles exceptions as valid outputs for scripts.
84
        elif child.tagName == 'exception':
85
            test_type = child.getAttribute('type')
86
            if test_type == '': test_type = DEFAULT_TEST_TYPE
87
            part.add_exception_test(getTextData(child), test_type)
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
88
        elif child.tagName == 'file':
89
            test_type = child.getAttribute('type')
90
            if test_type == '': test_type = DEFAULT_TEST_TYPE
91
            filename = child.getAttribute('name')
92
            if filename == '':
93
                raise ParseException("File without name in case %s" %case_name)
94
            part.add_file_test(filename, getTextData(child), test_type)
95
96
    return part
97
98
def getCaseData(caseNode):
99
    """ Creare a TestCase instance from test case xml data
100
    """
101
    
102
    case_name = caseNode.getAttribute('name')
103
    function = caseNode.getAttribute('function')
104
    if function == '': function = None
105
    case = TestCase(case_name, function)
106
    
107
    for child in caseNode.childNodes:
108
        if child.nodeType != child.ELEMENT_NODE:
109
            continue
110
111
        if child.tagName == 'stdin':
112
            # standard input
113
            case.set_stdin(getTextData(child))
114
        elif child.tagName == 'file':
115
            # file
116
            filename = child.getAttribute('name')
117
            if filename == '':
118
                raise ParseException("File without name in case %s" %case_name)
119
            case.add_file(filename, getTextData(child))
120
        elif child.tagName == 'var':
121
            # global variable
122
            var_name = child.getAttribute('name')
123
            var_val = child.getAttribute('value')
124
            if not var_name or not var_val:
125
                raise ParseException("Incomplete variable in case %s" %case_name)
126
            case.add_variable(var_name, var_val)
127
        elif child.tagName == 'arg':
128
            # function argument
129
            arg_val = child.getAttribute('value')
130
            arg_name = child.getAttribute('name')
131
            if arg_name == '': arg_name = None
132
            
133
            if not arg_val:
134
                raise ParseException("Incomplete argument in case %s" %case_name)
135
            case.add_arg(arg_val, arg_name)
299 by dilshan_a
Test framework now handles exceptions as valid outputs for scripts.
136
        elif child.tagName == 'exception':
137
            exception_name = child.getAttribute('name')
138
            if not exception_name:
139
                raise ParseException("Incomplete exception in case %s" %case_name)
140
            case.add_exception(exception_name)
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
141
        elif child.tagName == 'function':
142
            # specify a test case part
143
            case.add_part(getCasePartData(child))
144
145
    return case
146
                
147
def parse_tutorial_file(filename, prob_num=1):
148
    """ Parse an xml problem file and return a testsuite for that problem """
149
    dom = parse(filename)
150
151
    # get problem
152
    count = 0
153
    problem = None
154
    for child in dom.childNodes:
155
        if child.nodeType == child.ELEMENT_NODE and child.tagName == 'problem':
156
            count += 1
157
            if count == prob_num:
158
                problem = child
159
                break
160
161
    if problem == None:
162
        raise ParseException("Not enough problems")
163
164
    # get name
165
    problem_name = problem.getAttribute('name')
166
167
    if not problem_name:
168
        raise ParseException('Problem name not supplied')
169
170
    problem_suite = TestSuite(problem_name)
171
172
    # get solution and include info
173
    for child in problem.childNodes:
174
        if child.nodeType != child.ELEMENT_NODE:
175
            continue
176
        if child.tagName == 'solution':
177
            problem_suite.add_solution(getTextData(child))
178
        elif child.tagName == 'include':
179
            problem_suite.add_include_code(getTextData(child))
180
        elif child.tagName == 'case':
181
            problem_suite.add_case(getCaseData(child))
182
183
    return problem_suite
184