~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-12-08 03:50:24 UTC
  • mfrom: (1294.2.143 ui-the-third)
  • Revision ID: grantw@unimelb.edu.au-20091208035024-wjx8zp54gth15ph8
Merge ui-the-third. This is another UI revamp.

The header is now thin! Thin! The yellow bar is gone. The tabs are gone.
Breadcrumbs are here. Routes is replaced (with an object publishing
mechanism). Views are less repetitive. etc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
import os
23
23
import datetime
 
24
 
24
25
import genshi
 
26
from storm.locals import Store
25
27
 
26
 
import ivle.util
27
28
import ivle.console
28
29
import ivle.database
29
30
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, \
30
 
                          Offering, Subject, Semester, WorksheetExercise
31
 
import ivle.worksheet
32
 
import ivle.conf
 
31
                          Offering, Subject, Semester, User, WorksheetExercise
 
32
import ivle.worksheet.utils
33
33
import ivle.webapp.tutorial.test
34
 
 
35
34
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
36
35
                                   require_permission)
37
36
from ivle.webapp.errors import NotFound
38
37
 
39
 
# If True, getattempts or getattempt will allow browsing of inactive/disabled
40
 
# attempts. If False, will not allow this.
41
 
HISTORY_ALLOW_INACTIVE = False
42
38
 
43
39
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
44
40
 
45
41
class AttemptsRESTView(JSONRESTView):
46
42
    '''REST view of a user's attempts at an exercise.'''
47
 
    
48
 
    def __init__(self, req, subject, year, semester, worksheet, 
49
 
                                                exercise, username):
50
 
        self.user = ivle.database.User.get_by_login(req.store, username)
51
 
        if self.user is None:
52
 
            raise NotFound()
53
 
        
54
 
        self.worksheet_exercise = req.store.find(WorksheetExercise,
55
 
            WorksheetExercise.exercise_id == exercise,
56
 
            WorksheetExercise.worksheet_id == Worksheet.id,
57
 
            Worksheet.offering_id == Offering.id,
58
 
            Offering.subject_id == Subject.id,
59
 
            Subject.code == subject,
60
 
            Offering.semester_id == Semester.id,
61
 
            Semester.year == year,
62
 
            Semester.semester == semester).one()
63
 
        
64
 
        self.context = self.user # XXX: Not quite right.
65
43
 
66
44
    @require_permission('edit')
67
45
    def GET(self, req):
68
46
        """Handles a GET Attempts action."""
69
47
        attempts = req.store.find(ExerciseAttempt, 
70
 
                ExerciseAttempt.ws_ex_id == self.worksheet_exercise.id,
71
 
                ExerciseAttempt.user_id == self.user.id)
 
48
                ExerciseAttempt.ws_ex_id == self.context.worksheet_exercise.id,
 
49
                ExerciseAttempt.user_id == self.context.user.id)
72
50
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
73
51
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
74
52
        attempts = [{'date': time_fmt(a.date), 'complete': a.complete}
80
58
    @require_permission('edit')
81
59
    def PUT(self, req, data):
82
60
        """ Tests the given submission """
83
 
        exercise = req.store.find(Exercise, 
84
 
            Exercise.id == self.worksheet_exercise.exercise_id).one()
85
 
        if exercise is None:
86
 
            raise NotFound()
87
 
 
88
61
        # Start a console to run the tests on
89
 
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
 
62
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
 
63
                                 req.user.login)
90
64
        working_dir = os.path.join("/home", req.user.login)
91
 
        cons = ivle.console.Console(req.user.unixid, jail_path, working_dir)
 
65
        cons = ivle.console.Console(req.config, req.user.unixid, jail_path,
 
66
                                    working_dir)
92
67
 
93
68
        # Parse the file into a exercise object using the test suite
94
69
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
95
 
                                                            exercise, cons)
 
70
                            self.context.worksheet_exercise.exercise, cons)
96
71
 
97
72
        # Run the test cases. Get the result back as a JSONable object.
98
73
        # Return it.
102
77
        cons.close()
103
78
 
104
79
        attempt = ivle.database.ExerciseAttempt(user=req.user,
105
 
            worksheet_exercise = self.worksheet_exercise,
 
80
            worksheet_exercise = self.context.worksheet_exercise,
106
81
            date = datetime.datetime.now(),
107
82
            complete = test_results['passed'],
108
83
            text = unicode(data['code'])
113
88
        # Query the DB to get an updated score on whether or not this problem
114
89
        # has EVER been completed (may be different from "passed", if it has
115
90
        # been completed before), and the total number of attempts.
116
 
        completed, attempts = ivle.worksheet.get_exercise_status(req.store,
117
 
            req.user, self.worksheet_exercise)
 
91
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
 
92
                req.store, req.user, self.context.worksheet_exercise)
118
93
        test_results["completed"] = completed
119
94
        test_results["attempts"] = attempts
120
95
 
124
99
class AttemptRESTView(JSONRESTView):
125
100
    '''REST view of an exercise attempt.'''
126
101
 
127
 
    def __init__(self, req, subject, year, semester, worksheet, exercise, 
128
 
                 username, date):
129
 
        # TODO: Find exercise within worksheet.
130
 
        user = ivle.database.User.get_by_login(req.store, username)
131
 
        if user is None:
132
 
            raise NotFound()
133
 
 
134
 
        try:
135
 
            date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
136
 
        except ValueError:
137
 
            raise NotFound()
138
 
 
139
 
        worksheet_exercise = req.store.find(WorksheetExercise,
140
 
            WorksheetExercise.exercise_id == exercise,
141
 
            WorksheetExercise.worksheet_id == Worksheet.id,
142
 
            Worksheet.identifier == worksheet,
143
 
            Worksheet.offering_id == Offering.id,
144
 
            Offering.subject_id == Subject.id,
145
 
            Subject.code == subject,
146
 
            Offering.semester_id == Semester.id,
147
 
            Semester.year == year,
148
 
            Semester.semester == semester).one()
149
 
            
150
 
        attempt = ivle.worksheet.get_exercise_attempt(req.store, user,
151
 
                        worksheet_exercise, as_of=date,
152
 
                        allow_inactive=HISTORY_ALLOW_INACTIVE) 
153
 
 
154
 
        if attempt is None:
155
 
            raise NotFound()
156
 
 
157
 
        self.context = attempt
158
 
 
159
102
    @require_permission('view')
160
103
    def GET(self, req):
161
104
        return {'code': self.context.text}
162
105
 
163
106
 
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')
 
107
class WorksheetExerciseRESTView(JSONRESTView):
 
108
    '''REST view of a worksheet exercise.'''
 
109
 
 
110
    @named_operation('view')
177
111
    def save(self, req, text):
178
112
        # Find the appropriate WorksheetExercise to save to. If its not found,
179
113
        # 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()
192
114
 
193
115
        old_save = req.store.find(ExerciseSave,
194
 
            ExerciseSave.ws_ex_id == worksheet_exercise.id,
 
116
            ExerciseSave.ws_ex_id == self.context.id,
195
117
            ExerciseSave.user == req.user).one()
196
118
        
197
119
        #Overwrite the old, or create a new if there isn't one
201
123
        else:
202
124
            new_save = old_save
203
125
        
204
 
        new_save.worksheet_exercise = worksheet_exercise
 
126
        new_save.worksheet_exercise = self.context
205
127
        new_save.user = req.user
206
128
        new_save.text = unicode(text)
207
129
        new_save.date = datetime.datetime.now()
209
131
        return {"result": "ok"}
210
132
 
211
133
 
212
 
 
213
134
# Note that this is the view of an existing worksheet. Creation is handled
214
135
# by OfferingRESTView (as offerings have worksheets)
215
136
class WorksheetRESTView(JSONRESTView):
216
137
    """View used to update a worksheet."""
217
138
 
218
 
    def get_permissions(self, user):
219
 
        # XXX: Do it properly.
220
 
        # XXX: Lecturers should be allowed to add worksheets Only to subjects
221
 
        #      under their control
222
 
        if user is not None:
223
 
            if user.admin:
224
 
                return set(['save'])
225
 
            else:
226
 
                return set()
227
 
        else:
228
 
            return set()    
229
 
 
230
 
    def __init__(self, req, **kwargs):
231
 
    
232
 
        self.worksheet = kwargs['worksheet']
233
 
        self.subject = kwargs['subject']
234
 
        self.year = kwargs['year']
235
 
        self.semester = kwargs['semester']
236
 
    
237
 
        self.context = req.store.find(Worksheet,
238
 
            Worksheet.identifier == self.worksheet,
239
 
            Worksheet.offering_id == Offering.id,
240
 
            Offering.subject_id == Subject.id,
241
 
            Subject.code == self.subject,
242
 
            Offering.semester_id == Semester.id,
243
 
            Semester.year == self.year,
244
 
            Semester.semester == self.semester).one()
245
 
        
246
 
        if self.context is None:
247
 
            raise NotFound()
248
 
    
249
 
    @named_operation('save')
 
139
    @named_operation('edit')
250
140
    def save(self, req, name, assessable, data, format):
251
141
        """Takes worksheet data and saves it."""
252
142
        self.context.name = unicode(name)
253
143
        self.context.assessable = self.convert_bool(assessable)
254
144
        self.context.data = unicode(data)
255
145
        self.context.format = unicode(format)
256
 
        ivle.worksheet.update_exerciselist(self.context)
 
146
        ivle.worksheet.utils.update_exerciselist(self.context)
257
147
        
258
148
        return {"result": "ok"}
259
149
 
260
150
class WorksheetsRESTView(JSONRESTView):
261
151
    """View used to update and create Worksheets."""
262
 
    
263
 
    def get_permissions(self, user):
264
 
        # XXX: Do it properly.
265
 
        # XXX: Lecturers should be allowed to add worksheets Only to subjects
266
 
        #      under their control
267
 
        if user is not None:
268
 
            if user.admin:
269
 
                return set(['edit'])
270
 
            else:
271
 
                return set()
272
 
        else:
273
 
            return set()
274
 
 
275
 
    def __init__(self, req, **kwargs):
276
 
    
277
 
        self.subject = kwargs['subject']
278
 
        self.year = kwargs['year']
279
 
        self.semester = kwargs['semester']
280
 
    
281
 
        self.context = req.store.find(Offering,
282
 
            Offering.subject_id == Subject.id,
283
 
            Subject.code == self.subject,
284
 
            Offering.semester_id == Semester.id,
285
 
            Semester.year == self.year,
286
 
            Semester.semester == self.semester).one()
287
 
        
288
 
        if self.context is None:
289
 
            raise NotFound()
290
152
 
291
153
    @named_operation('edit')
292
154
    def add_worksheet(self, req, identifier, name, assessable, data, format):
305
167
        
306
168
        # This call is added for clarity, as the worksheet is implicitly added.        
307
169
        req.store.add(new_worksheet)
308
 
        
309
 
        ivle.worksheet.update_exerciselist(new_worksheet)
310
 
        
 
170
 
 
171
        ivle.worksheet.utils.update_exerciselist(new_worksheet)
 
172
 
311
173
        return {"result": "ok"}
312
174
 
313
175
    @named_operation('edit')