~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
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
22
import datetime
1294.2.64 by William Grant
Port tutorial stuff.
23
1099.4.3 by Nick Chadwick
Updated the tutorial service, to now allow users to edit worksheets
24
import genshi
1294.2.64 by William Grant
Port tutorial stuff.
25
from storm.locals import Store
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
26
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
27
import ivle.database
1099.4.3 by Nick Chadwick
Updated the tutorial service, to now allow users to edit worksheets
28
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, \
1294.2.64 by William Grant
Port tutorial stuff.
29
                          Offering, Subject, Semester, User, WorksheetExercise
1099.1.220 by Nick Chadwick
Merged from trunk
30
import ivle.worksheet.utils
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
31
from ivle.webapp.base.rest import (JSONRESTView, write_operation,
1099.1.113 by William Grant
Give console and tutorial services security declarations.
32
                                   require_permission)
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
1080.1.88 by William Grant
ivle.worksheet: Add a save_exercise function.
36
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
37
1394.2.8 by William Grant
Factor out console-based exercise testing into ivle.worksheet.test_exercise_submission().
38
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
39
class AttemptsRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
40
    '''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
41
1099.1.113 by William Grant
Give console and tutorial services security declarations.
42
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
43
    def GET(self, req):
44
        """Handles a GET Attempts action."""
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
45
        attempts = req.store.find(ExerciseAttempt, 
1294.2.64 by William Grant
Port tutorial stuff.
46
                ExerciseAttempt.ws_ex_id == self.context.worksheet_exercise.id,
47
                ExerciseAttempt.user_id == self.context.user.id)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
48
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
49
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
50
        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.
51
                for a in attempts]
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
52
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
53
        return attempts
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
54
55
1099.1.113 by William Grant
Give console and tutorial services security declarations.
56
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
57
    def PUT(self, req, data):
1099.1.114 by Nick Chadwick
Modified the database so that exercises are now stored in the database, rather
58
        """ Tests the given submission """
1821 by David Coles
Worksheets: Strip off whitespace from the end of exercise attempts.
59
        # Trim off any trailing whitespace (can cause syntax errors in python)
60
        # While technically this is a user error, it causes a lot of confusion 
61
        # for student since it's "invisible".
62
        code = data['code'].rstrip()
63
1394.2.8 by William Grant
Factor out console-based exercise testing into ivle.worksheet.test_exercise_submission().
64
        test_results = ivle.worksheet.utils.test_exercise_submission(
65
            req.config, req.user, self.context.worksheet_exercise.exercise,
1821 by David Coles
Worksheets: Strip off whitespace from the end of exercise attempts.
66
            code)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
67
68
        attempt = ivle.database.ExerciseAttempt(user=req.user,
1294.2.64 by William Grant
Port tutorial stuff.
69
            worksheet_exercise = self.context.worksheet_exercise,
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
70
            date = datetime.datetime.now(),
71
            complete = test_results['passed'],
1821 by David Coles
Worksheets: Strip off whitespace from the end of exercise attempts.
72
            text = unicode(code)
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
73
        )
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
74
75
        req.store.add(attempt)
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
        # Query the DB to get an updated score on whether or not this problem
78
        # has EVER been completed (may be different from "passed", if it has
79
        # been completed before), and the total number of attempts.
1099.1.220 by Nick Chadwick
Merged from trunk
80
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
1294.2.64 by William Grant
Port tutorial stuff.
81
                req.store, req.user, self.context.worksheet_exercise)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
82
        test_results["completed"] = completed
83
        test_results["attempts"] = attempts
84
85
        return test_results
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
86
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
87
88
class AttemptRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
89
    '''REST view of an exercise attempt.'''
90
1099.1.113 by William Grant
Give console and tutorial services security declarations.
91
    @require_permission('view')
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
92
    def GET(self, req):
93
        return {'code': self.context.text}
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
94
95
1099.1.216 by Nick Chadwick
Started adding in add and save options in the exercise edit view, to
96
class WorksheetExerciseRESTView(JSONRESTView):
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
97
    '''REST view of a worksheet exercise.'''
98
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
99
    @write_operation('view')
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
100
    def save(self, req, text):
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
101
        # Find the appropriate WorksheetExercise to save to. If its not found,
102
        # the user is submitting against a non-existant worksheet/exercise
103
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
104
        old_save = req.store.find(ExerciseSave,
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
105
            ExerciseSave.ws_ex_id == self.context.id,
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
106
            ExerciseSave.user == req.user).one()
107
        
108
        #Overwrite the old, or create a new if there isn't one
109
        if old_save is None:
110
            new_save = ExerciseSave()
111
            req.store.add(new_save)
112
        else:
113
            new_save = old_save
114
        
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
115
        new_save.worksheet_exercise = self.context
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
116
        new_save.user = req.user
117
        new_save.text = unicode(text)
118
        new_save.date = datetime.datetime.now()
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
119
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
120
        return {"result": "ok"}
1099.4.1 by Nick Chadwick
Working on putting worksheets into the database.
121
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
122
1099.1.189 by Nick Chadwick
Updated service.py to correctly add a seq_no to a worksheet before
123
class WorksheetsRESTView(JSONRESTView):
124
    """View used to update and create Worksheets."""
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
125
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
126
    @write_operation('edit_worksheets')
1099.1.197 by Nick Chadwick
Modified worksheets edit view, so now there are links to edit, add,
127
    def move_up(self, req, worksheetid):
128
        """Takes a list of worksheet-seq_no pairs and updates their 
129
        corresponding Worksheet objects to match."""
130
        
131
        worksheet_below = req.store.find(Worksheet,
132
            Worksheet.offering_id == self.context.id,
133
            Worksheet.identifier == unicode(worksheetid)).one()
134
        if worksheet_below is None:
135
            raise NotFound('worksheet_below')
136
        worksheet_above = req.store.find(Worksheet,
137
            Worksheet.offering_id == self.context.id,
138
            Worksheet.seq_no == (worksheet_below.seq_no - 1)).one()
139
        if worksheet_above is None:
140
            raise NotFound('worksheet_above')
141
142
        worksheet_below.seq_no = worksheet_below.seq_no - 1
143
        worksheet_above.seq_no = worksheet_above.seq_no + 1
144
        
145
        return {'result': 'ok'}
146
1796.1.2 by William Grant
Replace @named_operation with @read_operation and @write_operation. Allow execution of read operations with a GET rather than a POST.
147
    @write_operation('edit_worksheets')
1099.1.197 by Nick Chadwick
Modified worksheets edit view, so now there are links to edit, add,
148
    def move_down(self, req, worksheetid):
149
        """Takes a list of worksheet-seq_no pairs and updates their 
150
        corresponding Worksheet objects to match."""
151
        
152
        worksheet_above = req.store.find(Worksheet,
153
            Worksheet.offering_id == self.context.id,
154
            Worksheet.identifier == unicode(worksheetid)).one()
155
        if worksheet_above is None:
156
            raise NotFound('worksheet_below')
157
        worksheet_below = req.store.find(Worksheet,
158
            Worksheet.offering_id == self.context.id,
159
            Worksheet.seq_no == (worksheet_above.seq_no + 1)).one()
160
        if worksheet_below is None:
161
            raise NotFound('worksheet_above')
162
163
        worksheet_below.seq_no = worksheet_below.seq_no - 1
164
        worksheet_above.seq_no = worksheet_above.seq_no + 1
1099.1.189 by Nick Chadwick
Updated service.py to correctly add a seq_no to a worksheet before
165
        
166
        return {'result': 'ok'}