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

« back to all changes in this revision

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

MergedĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

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