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

« back to all changes in this revision

Viewing changes to ivle/webapp/admin/subject.py

  • Committer: William Grant
  • Date: 2010-07-30 01:16:11 UTC
  • Revision ID: grantw@unimelb.edu.au-20100730011611-ik9hj6yueeh6gc9h
Set version to 1.0.2rc1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
import urllib
28
28
import urlparse
29
29
import cgi
 
30
import datetime
30
31
 
31
32
from storm.locals import Desc, Store
32
33
import genshi
39
40
                                    DateTimeValidator)
40
41
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
41
42
from ivle.webapp.base.xhtml import XHTMLView
 
43
from ivle.webapp.base.text import TextView
42
44
from ivle.webapp.errors import BadRequest
43
45
from ivle.webapp import ApplicationRoot
44
46
 
73
75
        ctx['user'] = req.user
74
76
        ctx['semesters'] = []
75
77
 
76
 
        for semester in req.store.find(Semester).order_by(Desc(Semester.year),
77
 
                                                     Desc(Semester.semester)):
 
78
        for semester in req.store.find(Semester).order_by(
 
79
            Desc(Semester.year), Desc(Semester.display_name)):
78
80
            if req.user.admin:
79
81
                # For admins, show all subjects in the system
80
82
                offerings = list(semester.offerings.find())
102
104
 
103
105
        ctx['subjects'] = req.store.find(Subject).order_by(Subject.name)
104
106
        ctx['semesters'] = req.store.find(Semester).order_by(
105
 
            Semester.year, Semester.semester)
106
 
 
107
 
 
108
 
class SubjectShortNameUniquenessValidator(formencode.FancyValidator):
109
 
    """A FormEncode validator that checks that a subject name is unused.
 
107
            Semester.year, Semester.display_name)
 
108
 
 
109
 
 
110
class SubjectUniquenessValidator(formencode.FancyValidator):
 
111
    """A FormEncode validator that checks that a subject attribute is unique.
110
112
 
111
113
    The subject referenced by state.existing_subject is permitted
112
114
    to hold that name. If any other object holds it, the input is rejected.
 
115
 
 
116
    :param attribute: the name of the attribute to check.
 
117
    :param display: a string to identify the field in case of error.
113
118
    """
114
 
    def __init__(self, matching=None):
115
 
        self.matching = matching
 
119
 
 
120
    def __init__(self, attribute, display):
 
121
        self.attribute = attribute
 
122
        self.display = display
116
123
 
117
124
    def _to_python(self, value, state):
118
 
        if (state.store.find(
119
 
                Subject, short_name=value).one() not in
 
125
        if (state.store.find(Subject, **{self.attribute: value}).one() not in
120
126
                (None, state.existing_subject)):
121
127
            raise formencode.Invalid(
122
 
                'Short name already taken', value, state)
 
128
                '%s already taken' % self.display, value, state)
123
129
        return value
124
130
 
125
131
 
126
132
class SubjectSchema(formencode.Schema):
127
133
    short_name = formencode.All(
128
 
        SubjectShortNameUniquenessValidator(),
 
134
        SubjectUniquenessValidator('short_name', 'URL name'),
129
135
        URLNameValidator(not_empty=True))
130
136
    name = formencode.validators.UnicodeString(not_empty=True)
131
 
    code = formencode.validators.UnicodeString(not_empty=True)
 
137
    code = formencode.All(
 
138
        SubjectUniquenessValidator('code', 'Subject code'),
 
139
        formencode.validators.UnicodeString(not_empty=True))
132
140
 
133
141
 
134
142
class SubjectFormView(BaseFormView):
192
200
    """
193
201
    def _to_python(self, value, state):
194
202
        if (state.store.find(
195
 
                Semester, year=value['year'], semester=value['semester']
 
203
                Semester, year=value['year'], url_name=value['url_name']
196
204
                ).one() not in (None, state.existing_semester)):
197
205
            raise formencode.Invalid(
198
206
                'Semester already exists', value, state)
201
209
 
202
210
class SemesterSchema(formencode.Schema):
203
211
    year = URLNameValidator()
204
 
    semester = URLNameValidator()
 
212
    code = formencode.validators.UnicodeString()
 
213
    url_name = URLNameValidator()
 
214
    display_name = formencode.validators.UnicodeString()
205
215
    state = formencode.All(
206
216
        formencode.validators.OneOf(["past", "current", "future"]),
207
217
        formencode.validators.UnicodeString())
236
246
    def save_object(self, req, data):
237
247
        new_semester = Semester()
238
248
        new_semester.year = data['year']
239
 
        new_semester.semester = data['semester']
 
249
        new_semester.code = data['code']
 
250
        new_semester.url_name = data['url_name']
 
251
        new_semester.display_name = data['display_name']
240
252
        new_semester.state = data['state']
241
253
 
242
254
        req.store.add(new_semester)
253
265
    def get_default_data(self, req):
254
266
        return {
255
267
            'year': self.context.year,
256
 
            'semester': self.context.semester,
 
268
            'code': self.context.code,
 
269
            'url_name': self.context.url_name,
 
270
            'display_name': self.context.display_name,
257
271
            'state': self.context.state,
258
272
            }
259
273
 
260
274
    def save_object(self, req, data):
261
275
        self.context.year = data['year']
262
 
        self.context.semester = data['semester']
 
276
        self.context.code = data['code']
 
277
        self.context.url_name = data['url_name']
 
278
        self.context.display_name = data['display_name']
263
279
        self.context.state = data['state']
264
280
 
265
281
        return self.context
356
372
            year = semester = None
357
373
 
358
374
        semester = state.store.find(
359
 
            Semester, year=year, semester=semester).one()
 
375
            Semester, year=year, url_name=semester).one()
360
376
        if semester:
361
377
            return semester
362
378
        else:
416
432
        super(OfferingEdit, self).populate(req, ctx)
417
433
        ctx['subjects'] = req.store.find(Subject).order_by(Subject.name)
418
434
        ctx['semesters'] = req.store.find(Semester).order_by(
419
 
            Semester.year, Semester.semester)
 
435
            Semester.year, Semester.display_name)
420
436
        ctx['force_subject'] = None
421
437
 
422
438
    def populate_state(self, state):
426
442
        return {
427
443
            'subject': self.context.subject.short_name,
428
444
            'semester': self.context.semester.year + '/' +
429
 
                        self.context.semester.semester,
 
445
                        self.context.semester.url_name,
430
446
            'url': self.context.url,
431
447
            'description': self.context.description,
432
448
            'worksheet_cutoff': self.context.worksheet_cutoff,
460
476
        super(OfferingNew, self).populate(req, ctx)
461
477
        ctx['subjects'] = req.store.find(Subject).order_by(Subject.name)
462
478
        ctx['semesters'] = req.store.find(Semester).order_by(
463
 
            Semester.year, Semester.semester)
 
479
            Semester.year, Semester.display_name)
464
480
        ctx['force_subject'] = None
465
481
 
466
482
    def populate_state(self, state):
512
528
        super(OfferingCloneWorksheets, self).populate(req, ctx)
513
529
        ctx['subjects'] = req.store.find(Subject).order_by(Subject.name)
514
530
        ctx['semesters'] = req.store.find(Semester).order_by(
515
 
            Semester.year, Semester.semester)
 
531
            Semester.year, Semester.display_name)
516
532
 
517
533
    def get_default_data(self, req):
518
534
        return {}
735
751
    permission = "view_project_submissions"
736
752
    tab = 'subjects'
737
753
 
738
 
    def build_subversion_url(self, svnroot, submission):
739
 
        princ = submission.assessed.principal
740
 
 
741
 
        if isinstance(princ, User):
742
 
            path = 'users/%s' % princ.login
743
 
        else:
744
 
            path = 'groups/%s_%s_%s_%s' % (
745
 
                    princ.project_set.offering.subject.short_name,
746
 
                    princ.project_set.offering.semester.year,
747
 
                    princ.project_set.offering.semester.semester,
748
 
                    princ.name
749
 
                    )
750
 
        return urlparse.urljoin(
751
 
                    svnroot,
752
 
                    os.path.join(path, submission.path[1:] if
753
 
                                       submission.path.startswith(os.sep) else
754
 
                                       submission.path))
755
 
 
756
754
    def populate(self, req, ctx):
757
755
        self.plugin_styles[Plugin] = ["project.css"]
758
756
 
762
760
        ctx['EnrolView'] = EnrolView
763
761
        ctx['format_datetime'] = ivle.date.make_date_nice
764
762
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
765
 
        ctx['build_subversion_url'] = self.build_subversion_url
766
 
        ctx['svn_addr'] = req.config['urls']['svn_addr']
767
763
        ctx['project'] = self.context
768
764
        ctx['user'] = req.user
769
765
        ctx['ProjectEdit'] = ProjectEdit
770
766
        ctx['ProjectDelete'] = ProjectDelete
 
767
        ctx['ProjectExport'] = ProjectBashExportView
 
768
 
 
769
class ProjectBashExportView(TextView):
 
770
    """Produce a Bash script for exporting projects"""
 
771
    template = "templates/project-export.sh"
 
772
    content_type = "text/x-sh"
 
773
    permission = "view_project_submissions"
 
774
 
 
775
    def populate(self, req, ctx):
 
776
        ctx['req'] = req
 
777
        ctx['permissions'] = self.context.get_permissions(req.user,req.config)
 
778
        ctx['format_datetime'] = ivle.date.make_date_nice
 
779
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
 
780
        ctx['project'] = self.context
 
781
        ctx['user'] = req.user
 
782
        ctx['now'] = datetime.datetime.now()
 
783
        ctx['format_datetime'] = ivle.date.make_date_nice
 
784
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
771
785
 
772
786
class ProjectUniquenessValidator(formencode.FancyValidator):
773
787
    """A FormEncode validator that checks that a project short_name is unique
968
982
             (Project, '+index', ProjectView),
969
983
             (Project, '+edit', ProjectEdit),
970
984
             (Project, '+delete', ProjectDelete),
 
985
             (Project, ('+export', 'project-export.sh'),
 
986
                ProjectBashExportView),
971
987
             ]
972
988
 
973
989
    breadcrumbs = {Subject: SubjectBreadcrumb,