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

1099.1.114 by Nick Chadwick
Modified the database so that exercises are now stored in the database, rather
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, 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
        if child.nodeType == child.TEXT_NODE:
43
            data += child.data
44
45
    return data.strip()
46
47
def add_test_suite(suite_node, suite_num, store):
48
    """Given a test suite element, get all the cases it contains."""
49
    cases = []
50
    case_num = 0
51
    for case_node in suite_node.getElementsByTagName('function'):
52
        case_num += 1
53
        cases.append(add_test_case(case_node, case_num, store))
54
    new_suite = TestSuite()
55
    new_suite.description = suite_node.getAttribute('name')
56
    new_suite.seq_no = suite_num
57
    for testcase in cases:
58
        new_suite.test_cases.add(testcase)
59
    store.add(new_suite)
60
    return new_suite
61
62
63
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]
74
    #Now create the object to hold the data
75
    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
82
    new_test_case.seq_no = case_num
83
    store.add(new_test_case)
84
    return new_test_case
85
86
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()