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

« back to all changes in this revision

Viewing changes to bin/ivle-addexercise

  • Committer: chadnickbok
  • Date: 2009-02-02 04:00:25 UTC
  • Revision ID: svn-v4:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1189
Adding the changes from my genshi branch into trunk.

Most apps now use the Genshi templating engine, in preparation
for future changes to dispatch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
# IVLE - Informatics Virtual Learning Environment
3
 
# Copyright (C) 2007-2009 The University of Melbourne
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 
19
 
# Author:  Nicholas Chadwick
20
 
 
21
 
"""Script to upload an exercise file into the database"""
22
 
 
23
 
import os, sys
24
 
import xml.dom.minidom as minidom
25
 
 
26
 
from ivle.database import Exercise, TestSuite, TestCase, TestSuiteVar, TestCasePart, get_store
27
 
 
28
 
class XMLMalformedError(Exception):
29
 
    """Error thrown when encountering malformed data."""
30
 
    
31
 
    def __init__(self, text):
32
 
        self.msg = text
33
 
 
34
 
def getTextData(element):
35
 
    """ Get the text and cdata inside an element
36
 
    Leading and trailing whitespace are stripped
37
 
    """
38
 
    data = ''
39
 
    for child in element.childNodes:
40
 
        if child.nodeType == child.CDATA_SECTION_NODE:
41
 
            data += child.data
42
 
        elif child.nodeType == child.TEXT_NODE:
43
 
            data += child.data
44
 
        else:
45
 
            data += child.toxml()
46
 
 
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
58
 
 
59
 
def add_test_suite(suite_node, suite_num, store):
60
 
    """Given a test suite element, get all the cases it contains."""
61
 
    cases = []
62
 
    case_num = 0
63
 
    for case_node in suite_node.getElementsByTagName('function'):
64
 
        case_num += 1
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
 
    
110
 
    new_suite = TestSuite()
111
 
    new_suite.description = unicode(suite_node.getAttribute('name'))
112
 
    new_suite.seq_no = suite_num
113
 
    new_suite.function = unicode(suite_node.getAttribute('function'))
114
 
    new_suite.stdin = unicode(stdin)
115
 
    for testcase in cases:
116
 
        new_suite.test_cases.add(testcase)
117
 
    for var in suite_vars:
118
 
        new_suite.variables.add(var)
119
 
    store.add(new_suite)
120
 
    return new_suite
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
130
 
 
131
 
def add_test_case(case_node, case_num, store):
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
 
 
164
 
    #Now create the object to hold the data
165
 
    new_test_case = TestCase()
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'))
169
 
    new_test_case.seq_no = case_num
170
 
    store.add(new_test_case)
171
 
    for part in parts:
172
 
        new_test_case.parts.add(part)
173
 
    return new_test_case
174
 
 
175
 
xmlfile = sys.argv[1]
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()