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

« back to all changes in this revision

Viewing changes to bin/ivle-addexercise

Updated the exercises to be loaded from the database, not a local file.

This updated fixes some things broken in my previous commit, and now
it should leave the worksheets in a viewable (not working) state.

I have also updated ivle-addexercise and the database schema to reflect
the schema of an exercise.

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, element_type, test_type, data, filename=u""):
 
123
    new_part = TestCasePart()
 
124
    new_part.element_type = element_type
 
125
    new_part.test_type = test_type
 
126
    new_part.data = 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]
97
186
        sys.exit('ivle-addexercise: error parsing XML: root node must be "exercise"')
98
187
 
99
188
exercisename = exercise.getAttribute('name')
 
189
rows = exercise.getAttribute('rows')
100
190
solution = None
101
191
partial_solution = None
102
192
include_code = None
131
221
new_exercise = Exercise()
132
222
new_exercise.id = unicode(xmlfile)
133
223
new_exercise.name = exercisename
 
224
new_exercise.num_rows = int(rows)
134
225
new_exercise.partial = partial_solution
135
226
new_exercise.solution = solution
136
227
new_exercise.include = include_code