~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
1080.1.56 by Matt Giuca
Added new module: ivle.worksheet. This will contain general functions for
28
import ivle.worksheet
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
29
import ivle.conf
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
30
import ivle.webapp.tutorial.test
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
31
1099.1.113 by William Grant
Give console and tutorial services security declarations.
32
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
33
                                   require_permission)
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
34
from ivle.webapp.errors import NotFound
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
35
1025 by mattgiuca
tutorialservice: Added two new GET actions: getattempts and getattempt.
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
1080.1.88 by William Grant
ivle.worksheet: Add a save_exercise function.
40
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
41
42
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
43
class AttemptsRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
44
    '''REST view of a user's attempts at an exercise.'''
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
45
    def __init__(self, req, subject, worksheet, exercise, username):
46
        # TODO: Find exercise within worksheet.
47
        self.user = ivle.database.User.get_by_login(req.store, username)
48
        if self.user is None:
49
            raise NotFound()
50
        self.exercise = exercise
1099.1.113 by William Grant
Give console and tutorial services security declarations.
51
        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
52
1099.1.113 by William Grant
Give console and tutorial services security declarations.
53
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
54
    def GET(self, req):
55
        """Handles a GET Attempts action."""
56
        exercise = ivle.database.Exercise.get_by_name(req.store, 
57
                                                        self.exercise)
58
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
59
        attempts = ivle.worksheet.get_exercise_attempts(req.store, self.user,
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
60
                            exercise, allow_inactive=HISTORY_ALLOW_INACTIVE)
61
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
62
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
63
        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.
64
                for a in attempts]
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
65
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
66
        return attempts
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
67
68
1099.1.113 by William Grant
Give console and tutorial services security declarations.
69
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
70
    def PUT(self, req, data):
1099.1.114 by Nick Chadwick
Modified the database so that exercises are now stored in the database, rather
71
        """ Tests the given submission """
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
72
        exercisefile = ivle.util.open_exercise_file(self.exercise)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
73
        if exercisefile is None:
1099.1.93 by William Grant
Remove remaining uses of req.throw_error in the new webapps.
74
            raise NotFound()
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
75
76
        # Start a console to run the tests on
77
        jail_path = os.path.join(ivle.conf.jail_base, req.user.login)
78
        working_dir = os.path.join("/home", req.user.login)
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
79
        cons = ivle.console.Console(req.user.unixid, jail_path, working_dir)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
80
81
        # 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
82
        exercise_obj = ivle.webapp.tutorial.test.parse_exercise_file(
83
                                                            exercisefile, cons)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
84
        exercisefile.close()
85
86
        # Run the test cases. Get the result back as a JSONable object.
87
        # Return it.
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
88
        test_results = exercise_obj.run_tests(data['code'])
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
89
90
        # Close the console
91
        cons.close()
92
93
        # Get the Exercise from the database
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
94
        exercise = ivle.database.Exercise.get_by_name(req.store, self.exercise)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
95
96
        attempt = ivle.database.ExerciseAttempt(user=req.user,
97
                                                exercise=exercise,
98
                                                date=datetime.datetime.now(),
99
                                                complete=test_results['passed'],
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
100
                                                # XXX
101
                                                text=unicode(data['code']))
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
102
103
        req.store.add(attempt)
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
104
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
105
        # Query the DB to get an updated score on whether or not this problem
106
        # has EVER been completed (may be different from "passed", if it has
107
        # been completed before), and the total number of attempts.
108
        completed, attempts = ivle.worksheet.get_exercise_status(req.store,
109
            req.user, exercise)
110
        test_results["completed"] = completed
111
        test_results["attempts"] = attempts
112
113
        return test_results
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
114
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
115
116
class AttemptRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
117
    '''REST view of an exercise attempt.'''
118
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
119
    def __init__(self, req, subject, worksheet, exercise, username, date):
120
        # TODO: Find exercise within worksheet.
121
        user = ivle.database.User.get_by_login(req.store, username)
122
        if user is None:
123
            raise NotFound()
124
125
        try:
126
            date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
127
        except ValueError:
128
            raise NotFound()
129
130
        exercise = ivle.database.Exercise.get_by_name(req.store, exercise)
131
        attempt = ivle.worksheet.get_exercise_attempt(req.store, user,
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
132
            exercise, 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
133
134
        if attempt is None:
135
            raise NotFound()
136
137
        self.context = attempt
138
1099.1.113 by William Grant
Give console and tutorial services security declarations.
139
    @require_permission('view')
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
140
    def GET(self, req):
141
        return {'code': self.context.text}
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
142
143
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
144
class ExerciseRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
145
    '''REST view of an exercise.'''
1099.1.113 by William Grant
Give console and tutorial services security declarations.
146
147
    def get_permissions(self, user):
148
        # XXX: Do it properly.
149
        if user is not None:
150
            return set(['save'])
151
        else:
152
            return set()
153
154
    @named_operation('save')
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
155
    def save(self, req, text):
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
156
        # Need to open JUST so we know this is a real exercise.
157
        # (This avoids users submitting code for bogus exercises).
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
158
        exercisefile = ivle.util.open_exercise_file(self.exercise)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
159
        if exercisefile is None:
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
160
            raise NotFound()
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
161
        exercisefile.close()
162
163
        exercise = ivle.database.Exercise.get_by_name(req.store, self.exercise)
164
        ivle.worksheet.save_exercise(req.store, req.user, exercise,
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
165
                                     unicode(text), datetime.datetime.now())
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
166
        return {"result": "ok"}