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