~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-07-04 23:58:25 UTC
  • mto: (1294.4.2 ui-the-third)
  • mto: This revision was merged to the branch mainline in revision 1353.
  • Revision ID: grantw@unimelb.edu.au-20090704235825-2z5i3qkwj1gc7v7b
Port tutorial stuff.

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,
39
41
 
40
42
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
41
43
 
 
44
 
 
45
class ExerciseAttempts(object):
 
46
    """The set of exercise attempts for a user and exercise.
 
47
 
 
48
    A combination of a User and WorksheetExercise, this provides access to
 
49
    the User's ExerciseAttempts.
 
50
    """
 
51
 
 
52
    def __init__(self, worksheet_exercise, user):
 
53
        self.worksheet_exercise = worksheet_exercise
 
54
        self.user = user
 
55
 
 
56
    def get_permissions(self, user):
 
57
        return self.user.get_permissions(user)
 
58
 
 
59
 
 
60
def exerciseattempts_to_attempt(exercise_attempts, date):
 
61
    try:
 
62
        date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
 
63
    except ValueError:
 
64
        return None
 
65
 
 
66
    # XXX Hack around Google Code issue #87
 
67
    # Query from the given date +1 secnod.
 
68
    # Date is in seconds (eg. 3:47:12), while the data is in finer time
 
69
    # (eg. 3:47:12.3625). The query "date <= 3:47:12" will fail because
 
70
    # 3:47:12.3625 is greater. Hence we do the query from +1 second,
 
71
    # "date <= 3:47:13", and it finds the correct submission, UNLESS there
 
72
    # are multiple submissions inside the same second.
 
73
    date += datetime.timedelta(seconds=1)
 
74
 
 
75
    return ivle.worksheet.utils.get_exercise_attempt(
 
76
                Store.of(exercise_attempts.user),
 
77
                exercise_attempts.user, exercise_attempts.worksheet_exercise,
 
78
                as_of=date, allow_inactive=HISTORY_ALLOW_INACTIVE)
 
79
 
 
80
 
 
81
def worksheet_exercise_to_user_attempts(worksheet_exercise, login):
 
82
    user = User.get_by_login(Store.of(worksheet_exercise), login)
 
83
    if user is None:
 
84
        return None
 
85
    return ExerciseAttempts(worksheet_exercise, user)
 
86
 
 
87
 
 
88
def worksheet_to_worksheet_exercise(worksheet, exercise_name):
 
89
    return Store.of(worksheet).find(
 
90
        WorksheetExercise,
 
91
        WorksheetExercise.exercise_id == exercise_name,
 
92
        WorksheetExercise.worksheet == worksheet
 
93
        ).one()
 
94
 
 
95
 
42
96
class AttemptsRESTView(JSONRESTView):
43
97
    '''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
98
 
64
99
    @require_permission('edit')
65
100
    def GET(self, req):
66
101
        """Handles a GET Attempts action."""
67
102
        attempts = req.store.find(ExerciseAttempt, 
68
 
                ExerciseAttempt.ws_ex_id == self.worksheet_exercise.id,
69
 
                ExerciseAttempt.user_id == self.user.id)
 
103
                ExerciseAttempt.ws_ex_id == self.context.worksheet_exercise.id,
 
104
                ExerciseAttempt.user_id == self.context.user.id)
70
105
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
71
106
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
72
107
        attempts = [{'date': time_fmt(a.date), 'complete': a.complete}
78
113
    @require_permission('edit')
79
114
    def PUT(self, req, data):
80
115
        """ 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
116
        # Start a console to run the tests on
87
117
        jail_path = os.path.join(req.config['paths']['jails']['mounts'],
88
118
                                 req.user.login)
92
122
 
93
123
        # Parse the file into a exercise object using the test suite
94
124
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
95
 
                                                            exercise, cons)
 
125
                            self.context.worksheet_exercise.exercise, cons)
96
126
 
97
127
        # Run the test cases. Get the result back as a JSONable object.
98
128
        # Return it.
102
132
        cons.close()
103
133
 
104
134
        attempt = ivle.database.ExerciseAttempt(user=req.user,
105
 
            worksheet_exercise = self.worksheet_exercise,
 
135
            worksheet_exercise = self.context.worksheet_exercise,
106
136
            date = datetime.datetime.now(),
107
137
            complete = test_results['passed'],
108
138
            text = unicode(data['code'])
114
144
        # has EVER been completed (may be different from "passed", if it has
115
145
        # been completed before), and the total number of attempts.
116
146
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
117
 
                req.store, req.user, self.worksheet_exercise)
 
147
                req.store, req.user, self.context.worksheet_exercise)
118
148
        test_results["completed"] = completed
119
149
        test_results["attempts"] = attempts
120
150
 
124
154
class AttemptRESTView(JSONRESTView):
125
155
    '''REST view of an exercise attempt.'''
126
156
 
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
 
        # 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
 
        worksheet_exercise = req.store.find(WorksheetExercise,
149
 
            WorksheetExercise.exercise_id == exercise,
150
 
            WorksheetExercise.worksheet_id == Worksheet.id,
151
 
            Worksheet.identifier == worksheet,
152
 
            Worksheet.offering_id == Offering.id,
153
 
            Offering.subject_id == Subject.id,
154
 
            Subject.short_name == subject,
155
 
            Offering.semester_id == Semester.id,
156
 
            Semester.year == year,
157
 
            Semester.semester == semester).one()
158
 
            
159
 
        attempt = ivle.worksheet.utils.get_exercise_attempt(req.store, user,
160
 
                        worksheet_exercise, as_of=date,
161
 
                        allow_inactive=HISTORY_ALLOW_INACTIVE) 
162
 
 
163
 
        if attempt is None:
164
 
            raise NotFound()
165
 
 
166
 
        self.context = attempt
167
 
 
168
157
    @require_permission('view')
169
158
    def GET(self, req):
170
159
        return {'code': self.context.text}
173
162
class WorksheetExerciseRESTView(JSONRESTView):
174
163
    '''REST view of a worksheet exercise.'''
175
164
 
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
165
    @named_operation('view')
191
166
    def save(self, req, text):
192
167
        # Find the appropriate WorksheetExercise to save to. If its not found,
216
191
class WorksheetRESTView(JSONRESTView):
217
192
    """View used to update a worksheet."""
218
193
 
219
 
    def __init__(self, req, **kwargs):
220
 
    
221
 
        self.worksheet = kwargs['worksheet']
222
 
        self.subject = kwargs['subject']
223
 
        self.year = kwargs['year']
224
 
        self.semester = kwargs['semester']
225
 
    
226
 
        self.context = req.store.find(Worksheet,
227
 
            Worksheet.identifier == self.worksheet,
228
 
            Worksheet.offering_id == Offering.id,
229
 
            Offering.subject_id == Subject.id,
230
 
            Subject.short_name == self.subject,
231
 
            Offering.semester_id == Semester.id,
232
 
            Semester.year == self.year,
233
 
            Semester.semester == self.semester).one()
234
 
        
235
 
        if self.context is None:
236
 
            raise NotFound()
237
 
    
238
194
    @named_operation('edit')
239
195
    def save(self, req, name, assessable, data, format):
240
196
        """Takes worksheet data and saves it."""
248
204
 
249
205
class WorksheetsRESTView(JSONRESTView):
250
206
    """View used to update and create Worksheets."""
251
 
    
252
 
    def __init__(self, req, **kwargs):
253
 
    
254
 
        self.subject = kwargs['subject']
255
 
        self.year = kwargs['year']
256
 
        self.semester = kwargs['semester']
257
 
    
258
 
        self.context = req.store.find(Offering,
259
 
            Offering.subject_id == Subject.id,
260
 
            Subject.short_name == self.subject,
261
 
            Offering.semester_id == Semester.id,
262
 
            Semester.year == self.year,
263
 
            Semester.semester == self.semester).one()
264
 
        
265
 
        if self.context is None:
266
 
            raise NotFound()
267
207
 
268
208
    @named_operation('edit')
269
209
    def add_worksheet(self, req, identifier, name, assessable, data, format):