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

« back to all changes in this revision

Viewing changes to bin/ivle-addexercise

Quick port of fileservice to the new framework. It's still very much old-style,
though.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import os, sys
24
24
import xml.dom.minidom as minidom
25
25
 
26
 
from ivle.database import Exercise, TestSuite, TestCase, get_store
 
26
from ivle.database import Exercise, TestSuite, TestCase, TestSuiteVar, TestCasePart, get_store
27
27
 
28
28
class XMLMalformedError(Exception):
29
29
    """Error thrown when encountering malformed data."""
39
39
    for child in element.childNodes:
40
40
        if child.nodeType == child.CDATA_SECTION_NODE:
41
41
            data += child.data
42
 
        if child.nodeType == child.TEXT_NODE:
43
 
            data += child.data
 
42
        elif child.nodeType == child.TEXT_NODE:
 
43
            data += child.data
 
44
        else:
 
45
            data += child.toxml()
44
46
 
45
 
    return data.strip()
 
47
    return unicode(data.strip())
 
48
 
 
49
def add_var(store, var_type, var_name=u"", var_value=u"", arg_no=0):
 
50
    """Given an var node, parse it into a storm object."""
 
51
    new_var = TestSuiteVar()
 
52
    new_var.var_name = unicode(var_name)
 
53
    new_var.var_value = unicode(var_value)
 
54
    new_var.var_type = unicode(var_type)
 
55
    new_var.arg_no = arg_no
 
56
    store.add(new_var)
 
57
    return new_var
46
58
 
47
59
def add_test_suite(suite_node, suite_num, store):
48
60
    """Given a test suite element, get all the cases it contains."""
51
63
    for case_node in suite_node.getElementsByTagName('function'):
52
64
        case_num += 1
53
65
        cases.append(add_test_case(case_node, case_num, store))
 
66
 
 
67
    ## ALLOWED TAGS ##
 
68
    # stdin     - Stdin for the suite - Unique - Text inside element
 
69
    # file      - File to add to the filespace - Name - List
 
70
    # var       - Variable for the suite - Name/Value - List
 
71
    # arg       - Argument to functions - Name/Value - ORDERED List
 
72
    # exception - Allowed exception name - Name - List
 
73
    # function  - An actual test case
 
74
    suite_vars = []
 
75
    
 
76
    # Add file nodes
 
77
    file_nodes = suite_node.getElementsByTagName('file')
 
78
    for file_node in file_nodes:
 
79
        suite_vars.append(add_var(store, 'file', file_node.getAttribute('name')))
 
80
    
 
81
    # Add vars
 
82
    var_nodes = suite_node.getElementsByTagName('var')
 
83
    for var_node in var_nodes:
 
84
        var_name = var_node.getAttribute('name')
 
85
        var_value = var_node.getAttribute('value')
 
86
        suite_vars.append(add_var(store, 'var', var_name, var_value))
 
87
    
 
88
    # Args need to be numbered as they are found, as this order matters
 
89
    arg_num = 0
 
90
    for arg_node in suite_node.getElementsByTagName('arg'):
 
91
        suite_vars.append(add_var(store, 'arg', arg_node.getAttribute('name'),
 
92
                          arg_node.getAttribute('value'), arg_num))
 
93
        arg_num += 1
 
94
         
 
95
    # Add allowed exceptions
 
96
    exception_nodes = suite_node.getElementsByTagName('exception')
 
97
    for exception_node in exception_nodes:
 
98
        name = exception_node.getAttribute('name')
 
99
        suite_vars.append(add_var(store, 'exception', name))
 
100
    
 
101
    # Can only have 0-1 stdin elements
 
102
    stdin = suite_node.getElementsByTagName('stdin')
 
103
    if len(stdin) > 1:
 
104
        raise XMLMalformedError('Too many stdin tags found.')
 
105
    if stdin:
 
106
        stdin = getTextData(stdin[0])
 
107
    else:
 
108
        stdin = ""
 
109
    
54
110
    new_suite = TestSuite()
55
 
    new_suite.description = suite_node.getAttribute('name')
 
111
    new_suite.description = unicode(suite_node.getAttribute('name'))
56
112
    new_suite.seq_no = suite_num
 
113
    new_suite.function = unicode(suite_node.getAttribute('function'))
 
114
    new_suite.stdin = unicode(stdin)
57
115
    for testcase in cases:
58
116
        new_suite.test_cases.add(testcase)
 
117
    for var in suite_vars:
 
118
        new_suite.variables.add(var)
59
119
    store.add(new_suite)
60
120
    return new_suite
61
121
 
 
122
def add_part(store, part_type, test_type, data, filename=u""):
 
123
    new_part = TestCasePart()
 
124
    new_part.part_type = unicode(part_type)
 
125
    new_part.test_type = unicode(test_type)
 
126
    new_part.data = unicode(data)
 
127
    new_part.filename = unicode(filename)
 
128
    store.add(new_part)
 
129
    return new_part
62
130
 
63
131
def add_test_case(case_node, case_num, store):
64
 
    """Given a test case, generate its data"""
65
 
    # First perform basic error checks
66
 
    if not case_node.tagName == 'function': 
67
 
        raise XMLMalformedError(case_node.tagName + ' node')
68
 
    case_data = case_node.getElementsByTagName('code')
69
 
    if not case_data:
70
 
        case_data = case_node.getElementsByTagName('stdout')
71
 
    if not case_data:
72
 
        raise XMLMalformedError()
73
 
    case_data = case_data[0]
 
132
    """Given a test case node, parse it int a storm object."""
 
133
    
 
134
    ## ALLOWED TAGS ##
 
135
    # A function is allowed to contain the following elements 
 
136
    # stdout
 
137
    # stderr
 
138
    # result
 
139
    # exception
 
140
    # file
 
141
    # code
 
142
    allowed_parts = ['stdout', 'stderr', 'result', 'exception', 'file', 'code']
 
143
    parts = []
 
144
    for child_node in case_node.childNodes:
 
145
        if child_node.nodeType != child_node.ELEMENT_NODE:
 
146
            continue
 
147
        
 
148
        if child_node.tagName == 'file':
 
149
            part_type = 'file'
 
150
            test_type = child_node.getAttribute('type')
 
151
            data = getTextData(child_node)
 
152
            filename = child_node.getAttribute('name')
 
153
            if filename == "":
 
154
                raise XMLMalformedException('file tag must have names')
 
155
            parts.append(add_part(store, element_type, test_type, data,
 
156
                                        filename))
 
157
            
 
158
        elif child_node.tagName in allowed_parts:
 
159
            part_type = child_node.tagName
 
160
            test_type = child_node.getAttribute('type')
 
161
            data = getTextData(child_node)    
 
162
            parts.append(add_part(store, part_type, test_type, data))
 
163
 
74
164
    #Now create the object to hold the data
75
165
    new_test_case = TestCase()
76
 
    new_test_case.passmsg = case_node.getAttribute('pass')
77
 
    new_test_case.failmsg = case_node.getAttribute('fail')
78
 
    new_test_case.init = case_node.getAttribute('default')
79
 
    new_test_case.code_type = case_data.getAttribute('type')
80
 
    new_test_case.code = getTextData(case_data)
81
 
    new_test_case.testtype = case_data.tagName
 
166
    new_test_case.passmsg = unicode(case_node.getAttribute(u'pass'))
 
167
    new_test_case.failmsg = unicode(case_node.getAttribute(u'fail'))
 
168
    new_test_case.test_default = unicode(case_node.getAttribute(u'default'))
82
169
    new_test_case.seq_no = case_num
83
170
    store.add(new_test_case)
 
171
    for part in parts:
 
172
        new_test_case.parts.add(part)
84
173
    return new_test_case
85
174
 
86
175
xmlfile = sys.argv[1]
87
 
try:
88
 
    filedom = minidom.parse(xmlfile)
89
 
except IOError, e:
90
 
    sys.exit('ivle-addexercise: error opening file ' + xmlfile + ': ' + e[1])
91
 
 
92
 
 
93
 
for child in filedom.childNodes:
94
 
    if child.nodeType == child.ELEMENT_NODE and child.tagName == 'exercise':
95
 
        exercise = child
96
 
    else:
97
 
        sys.exit('ivle-addexercise: error parsing XML: root node must be "exercise"')
98
 
 
99
 
exercisename = exercise.getAttribute('name')
100
 
solution = None
101
 
partial_solution = None
102
 
include_code = None
103
 
description = None
104
 
test_suite_nodes = []
105
 
for child in exercise.childNodes:
106
 
    if child.nodeType != child.ELEMENT_NODE:
107
 
        continue
108
 
    if child.tagName == 'solution':
109
 
        if solution is not None:
110
 
            sys.exit('ivle-addexercise: error parsing XML: multiple "solution" nodes')
111
 
        solution = getTextData(child)
112
 
    elif child.tagName == 'include':
113
 
        if include_code is not None:
114
 
            sys.exit('ivle-addexercise: error parsing XML: multiple "include" nodes')
115
 
        include_code = getTextData(child)
116
 
    elif child.tagName == 'partial':
117
 
        if partial_solution is not None:
118
 
            sys.exit('ivle-addexercise: error parsing XML: multiple "include" nodes')
119
 
        partial_solution = getTextData(child)
120
 
    elif child.tagName == 'case':
121
 
        test_suite_nodes.append(child)
122
 
    elif child.tagName == 'desc':
123
 
        description = getTextData(child)
124
 
 
125
 
if solution is None:
126
 
    sys.exit("ivle-addexercise: error parsing XML: No solution given")
127
 
if len(test_suite_nodes) == 0:
128
 
    sys.exit("ivle-addexercise: error parsing XML:")
129
 
 
130
 
store = get_store()
131
 
new_exercise = Exercise()
132
 
new_exercise.id = unicode(xmlfile)
133
 
new_exercise.name = exercisename
134
 
new_exercise.partial = partial_solution
135
 
new_exercise.solution = solution
136
 
new_exercise.include = include_code
137
 
new_exercise.description = description
138
 
new_exercise.partial = partial_solution
139
 
store.add(new_exercise)
140
 
suite_num = 0
141
 
for suite in test_suite_nodes:
142
 
    new_exercise.test_suites.add(add_test_suite(suite, suite_num, store))
143
 
    suite_num += 1
144
 
 
145
 
store.add(new_exercise)
146
 
store.commit()
 
176
 
 
177
def add_exercise(xmlfile):
 
178
    try:
 
179
        filedom = minidom.parse(xmlfile)
 
180
    except IOError, e:
 
181
        raise Exception('ivle-addexercise: error opening file ' + xmlfile + ': ' + e[1])
 
182
 
 
183
    for child in filedom.childNodes:
 
184
        if child.nodeType == child.ELEMENT_NODE and child.tagName == 'exercise':
 
185
            exercise = child
 
186
        else:
 
187
            raise XMLMalformedError('ivle-addexercise: error parsing XML: root node must be "exercise"')
 
188
 
 
189
    exercisename = exercise.getAttribute('name')
 
190
    rows = exercise.getAttribute('rows')
 
191
    if rows == '':
 
192
        rows = 4
 
193
    solution = None
 
194
    partial_solution = None
 
195
    include_code = None
 
196
    description = None
 
197
    test_suite_nodes = []
 
198
    for child in exercise.childNodes:
 
199
        if child.nodeType != child.ELEMENT_NODE:
 
200
            continue
 
201
        if child.tagName == 'solution':
 
202
            if solution is not None:
 
203
                raise XMLMalformedError('ivle-addexercise: error parsing XML: multiple "solution" nodes')
 
204
            solution = getTextData(child)
 
205
        elif child.tagName == 'include':
 
206
            if include_code is not None:
 
207
                raise XMLMalformedError('ivle-addexercise: error parsing XML: multiple "include" nodes')
 
208
            include_code = getTextData(child)
 
209
        elif child.tagName == 'partial':
 
210
            if partial_solution is not None:
 
211
                raise XMLMalformedError('ivle-addexercise: error parsing XML: multiple "include" nodes')
 
212
            partial_solution = getTextData(child)
 
213
        elif child.tagName == 'case':
 
214
            test_suite_nodes.append(child)
 
215
        elif child.tagName == 'desc':
 
216
            description = getTextData(child)
 
217
 
 
218
    if solution is None:
 
219
        raise XMLMalformedError("ivle-addexercise: error parsing XML: No solution given")
 
220
    if len(test_suite_nodes) == 0:
 
221
        raise XMLMalformedError("ivle-addexercise: error parsing XML: No Tests Given!")
 
222
 
 
223
    store = get_store()
 
224
    new_exercise = Exercise()
 
225
    new_exercise.id = unicode(xmlfile)
 
226
    new_exercise.name = exercisename
 
227
    new_exercise.num_rows = int(rows)
 
228
    new_exercise.partial = partial_solution
 
229
    new_exercise.solution = solution
 
230
    new_exercise.include = include_code
 
231
    new_exercise.description = description
 
232
    new_exercise.partial = partial_solution
 
233
    store.add(new_exercise)
 
234
    suite_num = 0
 
235
    for suite in test_suite_nodes:
 
236
        new_exercise.test_suites.add(add_test_suite(suite, suite_num, store))
 
237
        suite_num += 1
 
238
 
 
239
    store.add(new_exercise)
 
240
    store.commit()
 
241
    
 
242
xmlfiles = sys.argv[1:]
 
243
for xmlfile in xmlfiles:
 
244
    print "Adding exercise", xmlfile
 
245
    #try:
 
246
    add_exercise(xmlfile)
 
247
    #except Exception, e:
 
248
    #    print "ERROR: Could not add file", xmlfile
 
249
    #    print e.stacktrace()