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

« back to all changes in this revision

Viewing changes to ivle/webapp/tutorial/service.py

  • Committer: William Grant
  • Date: 2009-02-24 13:29:44 UTC
  • Revision ID: grantw@unimelb.edu.au-20090224132944-lm29zd1li1rjg77p
Privileges (apart from admin) are now offering-local, not global.

Offering privileges are granted by Enrolment.role, and global admin
by User.admin. ivle.caps is dead.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import datetime
24
24
import genshi
25
25
 
 
26
import ivle.util
26
27
import ivle.console
27
28
import ivle.database
28
29
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, \
29
30
                          Offering, Subject, Semester, WorksheetExercise
30
 
import ivle.worksheet.utils
 
31
import ivle.worksheet
 
32
import ivle.conf
31
33
import ivle.webapp.tutorial.test
 
34
 
32
35
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
33
36
                                   require_permission)
34
37
from ivle.webapp.errors import NotFound
49
52
            raise NotFound()
50
53
        
51
54
        self.worksheet_exercise = req.store.find(WorksheetExercise,
52
 
            WorksheetExercise.exercise_id == unicode(exercise),
 
55
            WorksheetExercise.exercise_id == exercise,
53
56
            WorksheetExercise.worksheet_id == Worksheet.id,
54
57
            Worksheet.offering_id == Offering.id,
55
 
            Worksheet.identifier == unicode(worksheet),
56
58
            Offering.subject_id == Subject.id,
57
 
            Subject.short_name == subject,
 
59
            Subject.code == subject,
58
60
            Offering.semester_id == Semester.id,
59
61
            Semester.year == year,
60
62
            Semester.semester == semester).one()
84
86
            raise NotFound()
85
87
 
86
88
        # Start a console to run the tests on
87
 
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
88
 
                                 req.user.login)
 
89
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
89
90
        working_dir = os.path.join("/home", req.user.login)
90
 
        cons = ivle.console.Console(req.config, req.user.unixid, jail_path,
91
 
                                    working_dir)
 
91
        cons = ivle.console.Console(req.user.unixid, jail_path, working_dir)
92
92
 
93
93
        # Parse the file into a exercise object using the test suite
94
94
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
113
113
        # Query the DB to get an updated score on whether or not this problem
114
114
        # has EVER been completed (may be different from "passed", if it has
115
115
        # been completed before), and the total number of attempts.
116
 
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
117
 
                req.store, req.user, self.worksheet_exercise)
 
116
        completed, attempts = ivle.worksheet.get_exercise_status(req.store,
 
117
            req.user, self.worksheet_exercise)
118
118
        test_results["completed"] = completed
119
119
        test_results["attempts"] = attempts
120
120
 
136
136
        except ValueError:
137
137
            raise NotFound()
138
138
 
139
 
        # XXX Hack around Google Code issue #87
140
 
        # Query from the given date +1 secnod.
141
 
        # Date is in seconds (eg. 3:47:12), while the data is in finer time
142
 
        # (eg. 3:47:12.3625). The query "date <= 3:47:12" will fail because
143
 
        # 3:47:12.3625 is greater. Hence we do the query from +1 second,
144
 
        # "date <= 3:47:13", and it finds the correct submission, UNLESS there
145
 
        # are multiple submissions inside the same second.
146
 
        date += datetime.timedelta(seconds=1)
147
 
 
148
139
        worksheet_exercise = req.store.find(WorksheetExercise,
149
140
            WorksheetExercise.exercise_id == exercise,
150
141
            WorksheetExercise.worksheet_id == Worksheet.id,
151
142
            Worksheet.identifier == worksheet,
152
143
            Worksheet.offering_id == Offering.id,
153
144
            Offering.subject_id == Subject.id,
154
 
            Subject.short_name == subject,
 
145
            Subject.code == subject,
155
146
            Offering.semester_id == Semester.id,
156
147
            Semester.year == year,
157
148
            Semester.semester == semester).one()
158
149
            
159
 
        attempt = ivle.worksheet.utils.get_exercise_attempt(req.store, user,
 
150
        attempt = ivle.worksheet.get_exercise_attempt(req.store, user,
160
151
                        worksheet_exercise, as_of=date,
161
152
                        allow_inactive=HISTORY_ALLOW_INACTIVE) 
162
153
 
170
161
        return {'code': self.context.text}
171
162
 
172
163
 
173
 
class WorksheetExerciseRESTView(JSONRESTView):
174
 
    '''REST view of a worksheet exercise.'''
175
 
 
176
 
    def __init__(self, req, subject, year, semester, worksheet, exercise):
177
 
        self.context = req.store.find(WorksheetExercise,
178
 
            WorksheetExercise.exercise_id == exercise,
179
 
            WorksheetExercise.worksheet_id == Worksheet.id,
180
 
            Worksheet.offering_id == Offering.id,
181
 
            Offering.subject_id == Subject.id,
182
 
            Subject.short_name == subject,
183
 
            Offering.semester_id == Semester.id,
184
 
            Semester.year == year,
185
 
            Semester.semester == semester).one()
186
 
        
187
 
        if self.context is None:
188
 
            raise NotFound()
189
 
 
190
 
    @named_operation('view')
 
164
class ExerciseRESTView(JSONRESTView):
 
165
    '''REST view of an exercise.'''
 
166
 
 
167
    def get_permissions(self, user):
 
168
        # XXX: Do it properly.
 
169
        # XXX: Does any user have the ability to save as themselves?
 
170
        # XXX: Does a user EVER have permission to save as another user?
 
171
        if user is not None:
 
172
            return set(['save'])
 
173
        else:
 
174
            return set()
 
175
 
 
176
    @named_operation('save')
191
177
    def save(self, req, text):
192
178
        # Find the appropriate WorksheetExercise to save to. If its not found,
193
179
        # the user is submitting against a non-existant worksheet/exercise
 
180
        worksheet_exercise = req.store.find(WorksheetExercise,
 
181
            WorksheetExercise.exercise_id == self.exercise,
 
182
            WorksheetExercise.worksheet_id == Worksheet.id,
 
183
            Worksheet.offering_id == Offering.id,
 
184
            Offering.subject_id == Subject.id,
 
185
            Subject.code == self.subject,
 
186
            Offering.semester_id == Semester.id,
 
187
            Semester.year == self.year,
 
188
            Semester.semester == self.semester).one()
 
189
        
 
190
        if worksheet_exercise is None:
 
191
            raise NotFound()
194
192
 
195
193
        old_save = req.store.find(ExerciseSave,
196
 
            ExerciseSave.ws_ex_id == self.context.id,
 
194
            ExerciseSave.ws_ex_id == worksheet_exercise.id,
197
195
            ExerciseSave.user == req.user).one()
198
196
        
199
197
        #Overwrite the old, or create a new if there isn't one
203
201
        else:
204
202
            new_save = old_save
205
203
        
206
 
        new_save.worksheet_exercise = self.context
 
204
        new_save.worksheet_exercise = worksheet_exercise
207
205
        new_save.user = req.user
208
206
        new_save.text = unicode(text)
209
207
        new_save.date = datetime.datetime.now()
211
209
        return {"result": "ok"}
212
210
 
213
211
 
 
212
def generate_exerciselist(worksheet, req, worksheetdata):
 
213
    """Runs through the worksheetstream, generating the appropriate
 
214
    WorksheetExercises, and de-activating the old ones."""
 
215
    exercises = []
 
216
    # Turns the worksheet into an xml stream, and then finds all the 
 
217
    # exercise nodes in the stream.
 
218
    worksheetdata = genshi.XML(worksheetdata)
 
219
    for kind, data, pos in worksheetdata:
 
220
        if kind is genshi.core.START:
 
221
            # Data is a tuple of tag name and a list of name->value tuples
 
222
            if data[0] == 'exercise':
 
223
                src = ""
 
224
                optional = False
 
225
                for attr in data[1]:
 
226
                    if attr[0] == 'src':
 
227
                        src = attr[1]
 
228
                    if attr[0] == 'optional':
 
229
                        optional = attr[1] == 'true'
 
230
                if src != "":
 
231
                    exercises.append((src, optional))
 
232
    ex_num = 0
 
233
    # Set all current worksheet_exercises to be inactive
 
234
    db_worksheet_exercises = req.store.find(WorksheetExercise,
 
235
        WorksheetExercise.worksheet_id == worksheet.id)
 
236
    for worksheet_exercise in db_worksheet_exercises:
 
237
        worksheet_exercise.active = False
 
238
    
 
239
    for exerciseid, optional in exercises:
 
240
        worksheet_exercise = req.store.find(WorksheetExercise,
 
241
            WorksheetExercise.worksheet_id == worksheet.id,
 
242
            Exercise.id == WorksheetExercise.exercise_id,
 
243
            Exercise.id == exerciseid).one()
 
244
        if worksheet_exercise is None:
 
245
            exercise = req.store.find(Exercise,
 
246
                Exercise.id == exerciseid
 
247
            ).one()
 
248
            if exercise is None:
 
249
                raise NotFound()
 
250
            worksheet_exercise = WorksheetExercise()
 
251
            worksheet_exercise.worksheet_id = worksheet.id
 
252
            worksheet_exercise.exercise_id = exercise.id
 
253
            req.store.add(worksheet_exercise)
 
254
        worksheet_exercise.active = True
 
255
        worksheet_exercise.seq_no = ex_num
 
256
        worksheet_exercise.optional = optional
 
257
 
 
258
 
214
259
# Note that this is the view of an existing worksheet. Creation is handled
215
260
# by OfferingRESTView (as offerings have worksheets)
216
261
class WorksheetRESTView(JSONRESTView):
217
262
    """View used to update a worksheet."""
218
263
 
 
264
    def get_permissions(self, user):
 
265
        # XXX: Do it properly.
 
266
        # XXX: Lecturers should be allowed to add worksheets Only to subjects
 
267
        #      under their control
 
268
        if user is not None:
 
269
            if user.admin:
 
270
                return set(['save'])
 
271
            else:
 
272
                return set()
 
273
        else:
 
274
            return set()    
 
275
 
219
276
    def __init__(self, req, **kwargs):
220
277
    
221
278
        self.worksheet = kwargs['worksheet']
227
284
            Worksheet.identifier == self.worksheet,
228
285
            Worksheet.offering_id == Offering.id,
229
286
            Offering.subject_id == Subject.id,
230
 
            Subject.short_name == self.subject,
 
287
            Subject.code == self.subject,
231
288
            Offering.semester_id == Semester.id,
232
289
            Semester.year == self.year,
233
290
            Semester.semester == self.semester).one()
235
292
        if self.context is None:
236
293
            raise NotFound()
237
294
    
238
 
    @named_operation('edit')
 
295
    @named_operation('save')
239
296
    def save(self, req, name, assessable, data, format):
240
297
        """Takes worksheet data and saves it."""
 
298
        generate_exerciselist(self.context, req, data)
 
299
        
241
300
        self.context.name = unicode(name)
242
301
        self.context.assessable = self.convert_bool(assessable)
243
302
        self.context.data = unicode(data)
244
303
        self.context.format = unicode(format)
245
 
        ivle.worksheet.utils.update_exerciselist(self.context)
246
304
        
247
305
        return {"result": "ok"}
248
306
 
249
307
class WorksheetsRESTView(JSONRESTView):
250
308
    """View used to update and create Worksheets."""
251
309
    
 
310
    def get_permissions(self, user):
 
311
        # XXX: Do it properly.
 
312
        # XXX: Lecturers should be allowed to add worksheets Only to subjects
 
313
        #      under their control
 
314
        if user is not None:
 
315
            if user.admin:
 
316
                return set(['edit'])
 
317
            else:
 
318
                return set()
 
319
        else:
 
320
            return set()
 
321
 
252
322
    def __init__(self, req, **kwargs):
253
323
    
254
324
        self.subject = kwargs['subject']
257
327
    
258
328
        self.context = req.store.find(Offering,
259
329
            Offering.subject_id == Subject.id,
260
 
            Subject.short_name == self.subject,
 
330
            Subject.code == self.subject,
261
331
            Offering.semester_id == Semester.id,
262
332
            Semester.year == self.year,
263
333
            Semester.semester == self.semester).one()
282
352
        
283
353
        # This call is added for clarity, as the worksheet is implicitly added.        
284
354
        req.store.add(new_worksheet)
285
 
 
286
 
        ivle.worksheet.utils.update_exerciselist(new_worksheet)
287
 
 
 
355
        
 
356
        generate_exerciselist(new_worksheet, req, data)
 
357
        
288
358
        return {"result": "ok"}
289
359
 
290
360
    @named_operation('edit')