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

294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
1
# IVLE - Informatics Virtual Learning Environment
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
2
# Copyright (C) 2007-2009 The University of Melbourne
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
18
# Author: Matt Giuca, Nick Chadwick
19
20
'''AJAX backend for the tutorial application.'''
300 by mattgiuca
conf/apps: Added TutorialService as a registered app.
21
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
22
import os
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
23
import datetime
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
24
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
25
import ivle.util
26
import ivle.console
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
27
import ivle.database
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
28
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, Offering, Subject, Semester
1080.1.56 by Matt Giuca
Added new module: ivle.worksheet. This will contain general functions for
29
import ivle.worksheet
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
30
import ivle.conf
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
31
import ivle.webapp.tutorial.test
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
32
1099.1.113 by William Grant
Give console and tutorial services security declarations.
33
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
34
                                   require_permission)
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
35
from ivle.webapp.errors import NotFound
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
36
1025 by mattgiuca
tutorialservice: Added two new GET actions: getattempts and getattempt.
37
# If True, getattempts or getattempt will allow browsing of inactive/disabled
38
# attempts. If False, will not allow this.
39
HISTORY_ALLOW_INACTIVE = False
40
1080.1.88 by William Grant
ivle.worksheet: Add a save_exercise function.
41
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
42
43
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
44
class AttemptsRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
45
    '''REST view of a user's attempts at an exercise.'''
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
46
    def __init__(self, req, subject, year, semester, worksheet, 
47
                                                exercise, username):
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
48
        self.user = ivle.database.User.get_by_login(req.store, username)
49
        if self.user is None:
50
            raise NotFound()
51
        self.exercise = exercise
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
52
        
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
53
        self.worksheet = req.store.find(Worksheet,
54
            Worksheet.name == worksheet,
55
            Worksheet.offering_id == Offering.id,
56
            Offering.subject_id == Subject.id,
57
            Subject.code == subject,
58
            Offering.semester_id == Semester.id,
59
            Semester.year == year,
60
            Semester.semester == semester).one()
61
        
1099.1.113 by William Grant
Give console and tutorial services security declarations.
62
        self.context = self.user # XXX: Not quite right.
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
63
1099.1.113 by William Grant
Give console and tutorial services security declarations.
64
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
65
    def GET(self, req):
66
        """Handles a GET Attempts action."""
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
67
        exercise = req.store.find(Exercise, Exercise.id == self.exercise).one()
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
68
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
69
        attempts = req.store.find(ExerciseAttempt, 
70
                ExerciseAttempt.exercise_id == exercise.id,
71
                ExerciseAttempt.user_id == self.user.id)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
72
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
73
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
74
        attempts = [{'date': time_fmt(a.date), 'complete': a.complete}
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
75
                for a in attempts]
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
76
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
77
        return attempts
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
78
79
1099.1.113 by William Grant
Give console and tutorial services security declarations.
80
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
81
    def PUT(self, req, data):
1099.1.114 by Nick Chadwick
Modified the database so that exercises are now stored in the database, rather
82
        """ Tests the given submission """
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
83
        exercise = req.store.find(Exercise, Exercise.id == self.exercise).one()
84
        if exercise is None:
1099.1.93 by William Grant
Remove remaining uses of req.throw_error in the new webapps.
85
            raise NotFound()
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
86
87
        # Start a console to run the tests on
88
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
89
        working_dir = os.path.join("/home", req.user.login)
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
90
        cons = ivle.console.Console(req.user.unixid, jail_path, working_dir)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
91
92
        # Parse the file into a exercise object using the test suite
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
93
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
94
                                                            exercise, cons)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
95
96
        # Run the test cases. Get the result back as a JSONable object.
97
        # Return it.
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
98
        test_results = exercise_obj.run_tests(data['code'])
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
99
100
        # Close the console
101
        cons.close()
102
103
        attempt = ivle.database.ExerciseAttempt(user=req.user,
104
                                                exercise=exercise,
105
                                                date=datetime.datetime.now(),
106
                                                complete=test_results['passed'],
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
107
                                                worksheet=self.worksheet,
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
108
                                                text=unicode(data['code']))
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
109
110
        req.store.add(attempt)
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
111
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
112
        # Query the DB to get an updated score on whether or not this problem
113
        # has EVER been completed (may be different from "passed", if it has
114
        # been completed before), and the total number of attempts.
115
        completed, attempts = ivle.worksheet.get_exercise_status(req.store,
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
116
            req.user, exercise, self.worksheet)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
117
        test_results["completed"] = completed
118
        test_results["attempts"] = attempts
119
120
        return test_results
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
121
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
122
123
class AttemptRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
124
    '''REST view of an exercise attempt.'''
125
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
126
    def __init__(self, req, subject, worksheet, exercise, username, date):
127
        # TODO: Find exercise within worksheet.
128
        user = ivle.database.User.get_by_login(req.store, username)
129
        if user is None:
130
            raise NotFound()
131
132
        try:
133
            date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
134
        except ValueError:
135
            raise NotFound()
136
137
        exercise = ivle.database.Exercise.get_by_name(req.store, exercise)
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
138
        worksheet = req.store.find(Worksheet,
139
            Worksheet.name == self.worksheet,
140
            Worksheet.offering_id == Offering.id,
141
            Offering.subject_id == Subject.id,
142
            Subject.code == self.subject,
143
            Offering.semester_id == Semester.id,
144
            Semester.year == self.year,
145
            Semester.semester == self.semester).one()
146
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
147
        attempt = ivle.worksheet.get_exercise_attempt(req.store, user,
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
148
            exercise, worksheet, as_of=date, allow_inactive=HISTORY_ALLOW_INACTIVE)
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
149
150
        if attempt is None:
151
            raise NotFound()
152
153
        self.context = attempt
154
1099.1.113 by William Grant
Give console and tutorial services security declarations.
155
    @require_permission('view')
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
156
    def GET(self, req):
157
        return {'code': self.context.text}
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
158
159
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
160
class ExerciseRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
161
    '''REST view of an exercise.'''
1099.1.113 by William Grant
Give console and tutorial services security declarations.
162
163
    def get_permissions(self, user):
164
        # XXX: Do it properly.
165
        if user is not None:
166
            return set(['save'])
167
        else:
168
            return set()
169
170
    @named_operation('save')
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
171
    def save(self, req, text):
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
172
        # Need to open JUST so we know this is a real exercise.
173
        # (This avoids users submitting code for bogus exercises).
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
174
        exercise = req.store.find(Exercise,
175
            Exercise.id == self.exercise).one()
1099.1.150 by Nick Chadwick
Modified worksheets to properly link attempts to worksheets and
176
        worksheet = req.store.find(Worksheet,
177
            Worksheet.name == self.worksheet,
178
            Worksheet.offering_id == Offering.id,
179
            Offering.subject_id == Subject.id,
180
            Subject.code == self.subject,
181
            Offering.semester_id == Semester.id,
182
            Semester.year == self.year,
183
            Semester.semester == self.semester).one()
184
        ivle.worksheet.save_exercise(req.store, req.user, exercise, worksheet,
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
185
                                     unicode(text), datetime.datetime.now())
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
186
        return {"result": "ok"}