~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-02 04:02:19 UTC
  • mto: This revision was merged to the branch mainline in revision 1353.
  • Revision ID: grantw@unimelb.edu.au-20091202040219-z2qumlxdkmestikd
Use a different set of routes for public mode, too.

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
28
import ivle.console
27
29
import ivle.database
28
30
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, \
29
 
                          Offering, Subject, Semester, WorksheetExercise
 
31
                          Offering, Subject, Semester, User, WorksheetExercise
30
32
import ivle.worksheet.utils
31
33
import ivle.webapp.tutorial.test
32
34
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
33
35
                                   require_permission)
34
36
from ivle.webapp.errors import NotFound
35
37
 
36
 
# If True, getattempts or getattempt will allow browsing of inactive/disabled
37
 
# attempts. If False, will not allow this.
38
 
HISTORY_ALLOW_INACTIVE = False
39
38
 
40
39
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
41
40
 
42
41
class AttemptsRESTView(JSONRESTView):
43
42
    '''REST view of a user's attempts at an exercise.'''
44
 
    
45
 
    def __init__(self, req, subject, year, semester, worksheet, 
46
 
                                                exercise, username):
47
 
        self.user = ivle.database.User.get_by_login(req.store, username)
48
 
        if self.user is None:
49
 
            raise NotFound()
50
 
        
51
 
        self.worksheet_exercise = req.store.find(WorksheetExercise,
52
 
            WorksheetExercise.exercise_id == unicode(exercise),
53
 
            WorksheetExercise.worksheet_id == Worksheet.id,
54
 
            Worksheet.offering_id == Offering.id,
55
 
            Worksheet.identifier == unicode(worksheet),
56
 
            Offering.subject_id == Subject.id,
57
 
            Subject.short_name == subject,
58
 
            Offering.semester_id == Semester.id,
59
 
            Semester.year == year,
60
 
            Semester.semester == semester).one()
61
 
        
62
 
        self.context = self.user # XXX: Not quite right.
63
43
 
64
44
    @require_permission('edit')
65
45
    def GET(self, req):
66
46
        """Handles a GET Attempts action."""
67
47
        attempts = req.store.find(ExerciseAttempt, 
68
 
                ExerciseAttempt.ws_ex_id == self.worksheet_exercise.id,
69
 
                ExerciseAttempt.user_id == self.user.id)
 
48
                ExerciseAttempt.ws_ex_id == self.context.worksheet_exercise.id,
 
49
                ExerciseAttempt.user_id == self.context.user.id)
70
50
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
71
51
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
72
52
        attempts = [{'date': time_fmt(a.date), 'complete': a.complete}
78
58
    @require_permission('edit')
79
59
    def PUT(self, req, data):
80
60
        """ Tests the given submission """
81
 
        exercise = req.store.find(Exercise, 
82
 
            Exercise.id == self.worksheet_exercise.exercise_id).one()
83
 
        if exercise is None:
84
 
            raise NotFound()
85
 
 
86
61
        # Start a console to run the tests on
87
62
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
88
63
                                 req.user.login)
89
64
        working_dir = os.path.join("/home", req.user.login)
90
 
        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)
91
67
 
92
68
        # Parse the file into a exercise object using the test suite
93
69
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
94
 
                                                            exercise, cons)
 
70
                            self.context.worksheet_exercise.exercise, cons)
95
71
 
96
72
        # Run the test cases. Get the result back as a JSONable object.
97
73
        # Return it.
101
77
        cons.close()
102
78
 
103
79
        attempt = ivle.database.ExerciseAttempt(user=req.user,
104
 
            worksheet_exercise = self.worksheet_exercise,
 
80
            worksheet_exercise = self.context.worksheet_exercise,
105
81
            date = datetime.datetime.now(),
106
82
            complete = test_results['passed'],
107
83
            text = unicode(data['code'])
113
89
        # has EVER been completed (may be different from "passed", if it has
114
90
        # been completed before), and the total number of attempts.
115
91
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
116
 
                req.store, req.user, self.worksheet_exercise)
 
92
                req.store, req.user, self.context.worksheet_exercise)
117
93
        test_results["completed"] = completed
118
94
        test_results["attempts"] = attempts
119
95
 
123
99
class AttemptRESTView(JSONRESTView):
124
100
    '''REST view of an exercise attempt.'''
125
101
 
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
 
        # XXX Hack around Google Code issue #87
139
 
        # Query from the given date +1 secnod.
140
 
        # Date is in seconds (eg. 3:47:12), while the data is in finer time
141
 
        # (eg. 3:47:12.3625). The query "date <= 3:47:12" will fail because
142
 
        # 3:47:12.3625 is greater. Hence we do the query from +1 second,
143
 
        # "date <= 3:47:13", and it finds the correct submission, UNLESS there
144
 
        # are multiple submissions inside the same second.
145
 
        date += datetime.timedelta(seconds=1)
146
 
 
147
 
        worksheet_exercise = req.store.find(WorksheetExercise,
148
 
            WorksheetExercise.exercise_id == exercise,
149
 
            WorksheetExercise.worksheet_id == Worksheet.id,
150
 
            Worksheet.identifier == worksheet,
151
 
            Worksheet.offering_id == Offering.id,
152
 
            Offering.subject_id == Subject.id,
153
 
            Subject.short_name == subject,
154
 
            Offering.semester_id == Semester.id,
155
 
            Semester.year == year,
156
 
            Semester.semester == semester).one()
157
 
            
158
 
        attempt = ivle.worksheet.utils.get_exercise_attempt(req.store, user,
159
 
                        worksheet_exercise, as_of=date,
160
 
                        allow_inactive=HISTORY_ALLOW_INACTIVE) 
161
 
 
162
 
        if attempt is None:
163
 
            raise NotFound()
164
 
 
165
 
        self.context = attempt
166
 
 
167
102
    @require_permission('view')
168
103
    def GET(self, req):
169
104
        return {'code': self.context.text}
172
107
class WorksheetExerciseRESTView(JSONRESTView):
173
108
    '''REST view of a worksheet exercise.'''
174
109
 
175
 
    def __init__(self, req, subject, year, semester, worksheet, exercise):
176
 
        self.context = req.store.find(WorksheetExercise,
177
 
            WorksheetExercise.exercise_id == exercise,
178
 
            WorksheetExercise.worksheet_id == Worksheet.id,
179
 
            Worksheet.offering_id == Offering.id,
180
 
            Offering.subject_id == Subject.id,
181
 
            Subject.short_name == subject,
182
 
            Offering.semester_id == Semester.id,
183
 
            Semester.year == year,
184
 
            Semester.semester == semester).one()
185
 
        
186
 
        if self.context is None:
187
 
            raise NotFound()
188
 
 
189
110
    @named_operation('view')
190
111
    def save(self, req, text):
191
112
        # Find the appropriate WorksheetExercise to save to. If its not found,
215
136
class WorksheetRESTView(JSONRESTView):
216
137
    """View used to update a worksheet."""
217
138
 
218
 
    def __init__(self, req, **kwargs):
219
 
    
220
 
        self.worksheet = kwargs['worksheet']
221
 
        self.subject = kwargs['subject']
222
 
        self.year = kwargs['year']
223
 
        self.semester = kwargs['semester']
224
 
    
225
 
        self.context = req.store.find(Worksheet,
226
 
            Worksheet.identifier == self.worksheet,
227
 
            Worksheet.offering_id == Offering.id,
228
 
            Offering.subject_id == Subject.id,
229
 
            Subject.short_name == self.subject,
230
 
            Offering.semester_id == Semester.id,
231
 
            Semester.year == self.year,
232
 
            Semester.semester == self.semester).one()
233
 
        
234
 
        if self.context is None:
235
 
            raise NotFound()
236
 
    
237
139
    @named_operation('edit')
238
140
    def save(self, req, name, assessable, data, format):
239
141
        """Takes worksheet data and saves it."""
247
149
 
248
150
class WorksheetsRESTView(JSONRESTView):
249
151
    """View used to update and create Worksheets."""
250
 
    
251
 
    def __init__(self, req, **kwargs):
252
 
    
253
 
        self.subject = kwargs['subject']
254
 
        self.year = kwargs['year']
255
 
        self.semester = kwargs['semester']
256
 
    
257
 
        self.context = req.store.find(Offering,
258
 
            Offering.subject_id == Subject.id,
259
 
            Subject.short_name == self.subject,
260
 
            Offering.semester_id == Semester.id,
261
 
            Semester.year == self.year,
262
 
            Semester.semester == self.semester).one()
263
 
        
264
 
        if self.context is None:
265
 
            raise NotFound()
266
152
 
267
153
    @named_operation('edit')
268
154
    def add_worksheet(self, req, identifier, name, assessable, data, format):