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

« back to all changes in this revision

Viewing changes to ivle/webapp/tutorial/publishing.py

  • Committer: David Coles
  • Date: 2010-02-23 09:28:32 UTC
  • Revision ID: coles.david@gmail.com-20100223092832-5jsmysvrmdensnhg
exercises: Show error for bad reStructuredText rather than crashing

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
 
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
 
 
18
import datetime
 
19
 
 
20
from storm.locals import Store
 
21
 
 
22
from ivle.database import (Exercise, ExerciseAttempt, Offering, User,
 
23
                           Worksheet, WorksheetExercise)
 
24
 
 
25
from ivle.webapp import ApplicationRoot
 
26
from ivle.webapp.publisher import ROOT
 
27
from ivle.webapp.publisher.decorators import forward_route, reverse_route
 
28
 
 
29
import ivle.worksheet
 
30
 
 
31
from ivle.webapp.tutorial.service import TIMESTAMP_FORMAT
 
32
 
 
33
# If True, getattempts or getattempt will allow browsing of inactive/disabled
 
34
# attempts. If False, will not allow this.
 
35
HISTORY_ALLOW_INACTIVE = False
 
36
 
 
37
@forward_route(ApplicationRoot, '+exercises', argc=1)
 
38
def root_to_exercise(root, exercise_name):
 
39
    return root.store.find(
 
40
        Exercise,
 
41
        Exercise.id == exercise_name
 
42
        ).one()
 
43
 
 
44
@reverse_route(Exercise)
 
45
def exercise_url(exercise):
 
46
    return (ROOT, ('+exercises', exercise.id))
 
47
 
 
48
 
 
49
@forward_route(Offering, '+worksheets', argc=1)
 
50
def offering_to_worksheet(offering, worksheet_name):
 
51
    return Store.of(offering).find(
 
52
        Worksheet,
 
53
        Worksheet.offering == offering,
 
54
        Worksheet.identifier == worksheet_name
 
55
        ).one()
 
56
 
 
57
@reverse_route(Worksheet)
 
58
def worksheet_url(worksheet):
 
59
    return (worksheet.offering, ('+worksheets', worksheet.identifier))
 
60
 
 
61
 
 
62
@forward_route(Worksheet, argc=1)
 
63
def worksheet_to_worksheetexercise(worksheet, exercise_name):
 
64
    return Store.of(worksheet).find(
 
65
        WorksheetExercise,
 
66
        WorksheetExercise.exercise_id == exercise_name,
 
67
        WorksheetExercise.worksheet == worksheet
 
68
        ).one()
 
69
 
 
70
@reverse_route(WorksheetExercise)
 
71
def worksheetexercise_url(worksheetexercise):
 
72
    return (worksheetexercise.worksheet,
 
73
            worksheetexercise.exercise.identifier)
 
74
 
 
75
 
 
76
class ExerciseAttempts(object):
 
77
    """The set of exercise attempts for a user and exercise.
 
78
 
 
79
    A combination of a User and WorksheetExercise, this provides access to
 
80
    the User's ExerciseAttempts.
 
81
    """
 
82
 
 
83
    def __init__(self, worksheet_exercise, user):
 
84
        self.worksheet_exercise = worksheet_exercise
 
85
        self.user = user
 
86
 
 
87
    def get_permissions(self, user, config):
 
88
        return self.user.get_permissions(user, config)
 
89
 
 
90
 
 
91
@forward_route(WorksheetExercise, '+attempts', argc=1)
 
92
def worksheetexercise_to_exerciseattempts(worksheet_exercise, login):
 
93
    user = User.get_by_login(Store.of(worksheet_exercise), login)
 
94
    if user is None:
 
95
        return None
 
96
    return ExerciseAttempts(worksheet_exercise, user)
 
97
 
 
98
@reverse_route(ExerciseAttempts)
 
99
def exerciseattempts_url(exerciseattempts):
 
100
    return (exerciseattempts.worksheet_exercise,
 
101
            ('+attempts', exerciseattempts.user.login))
 
102
 
 
103
 
 
104
@forward_route(ExerciseAttempts, argc=1)
 
105
def exerciseattempts_to_attempt(exercise_attempts, date):
 
106
    try:
 
107
        date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
 
108
    except ValueError:
 
109
        return None
 
110
 
 
111
    # XXX Hack around Google Code issue #87
 
112
    # Query from the given date +1 secnod.
 
113
    # Date is in seconds (eg. 3:47:12), while the data is in finer time
 
114
    # (eg. 3:47:12.3625). The query "date <= 3:47:12" will fail because
 
115
    # 3:47:12.3625 is greater. Hence we do the query from +1 second,
 
116
    # "date <= 3:47:13", and it finds the correct submission, UNLESS there
 
117
    # are multiple submissions inside the same second.
 
118
    date += datetime.timedelta(seconds=1)
 
119
 
 
120
    return ivle.worksheet.utils.get_exercise_attempt(
 
121
                Store.of(exercise_attempts.user),
 
122
                exercise_attempts.user, exercise_attempts.worksheet_exercise,
 
123
                as_of=date, allow_inactive=HISTORY_ALLOW_INACTIVE)
 
124
 
 
125
@reverse_route(ExerciseAttempt)
 
126
def exerciseattempt_url(exerciseattempt):
 
127
    return (ExerciseAttempts(exerciseattempt.worksheet_exercise,
 
128
                             exerciseattempt.user),
 
129
            exerciseattempt.date.strftime(TIMESTAMP_FORMAT)
 
130
            )