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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: David Coles
  • Date: 2010-07-17 11:32:50 UTC
  • Revision ID: coles.david@gmail.com-20100717113250-vi18n50bcjmfmzrt
Show warning for CGI header field-names which contain restricted characters.

Forbidden characters are the separators defined by RFC3875. This is mainly to 
fix an issue where printing a dictionary (with no CGI headers) could be 
assumed to be a CGI header with no warnings.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
import datetime
28
28
import os
29
29
import urlparse
30
 
import urllib
31
30
 
32
31
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
33
32
                         Reference, ReferenceSet, Bool, Storm, Desc
150
149
            Offering.semester_id == Semester.id,
151
150
            Offering.subject_id == Subject.id).order_by(
152
151
                Desc(Semester.year),
153
 
                Desc(Semester.display_name),
 
152
                Desc(Semester.semester),
154
153
                Desc(Subject.code)
155
154
            )
156
155
 
231
230
        """Find a user in a store by login name."""
232
231
        return store.find(cls, cls.login == unicode(login)).one()
233
232
 
234
 
    def get_svn_url(self, config):
 
233
    def get_svn_url(self, config, req):
235
234
        """Get the subversion repository URL for this user or group."""
236
 
        url = config['urls']['svn_addr']
 
235
        login = req.user.login
 
236
        url = urlparse.urlsplit(config['urls']['svn_addr'])
 
237
        url = urlparse.urlunsplit(url[:1] + (login+'@'+url[1],) + url[2:])
237
238
        path = 'users/%s' % self.login
238
239
        return urlparse.urljoin(url, path)
239
240
 
298
299
        """
299
300
        return self.offerings.find(Offering.semester_id == Semester.id,
300
301
                               Semester.year == unicode(year),
301
 
                               Semester.url_name == unicode(semester)).one()
 
302
                               Semester.semester == unicode(semester)).one()
302
303
 
303
304
class Semester(Storm):
304
305
    """A semester in which subjects can be run."""
307
308
 
308
309
    id = Int(primary=True, name="semesterid")
309
310
    year = Unicode()
310
 
    code = Unicode()
311
 
    url_name = Unicode()
312
 
    display_name = Unicode()
 
311
    semester = Unicode()
313
312
    state = Unicode()
314
313
 
315
314
    offerings = ReferenceSet(id, 'Offering.semester_id')
321
320
    __init__ = _kwarg_init
322
321
 
323
322
    def __repr__(self):
324
 
        return "<%s %s/%s>" % (type(self).__name__, self.year, self.code)
 
323
        return "<%s %s/%s>" % (type(self).__name__, self.year, self.semester)
325
324
 
326
325
class Offering(Storm):
327
326
    """An offering of a subject in a particular semester."""
612
611
        return "<%s '%s' in %r>" % (type(self).__name__, self.short_name,
613
612
                                  self.project_set.offering)
614
613
 
615
 
    def can_submit(self, principal, user, late=False):
616
 
        """
617
 
        @param late: If True, does not take the deadline into account.
618
 
        """
 
614
    def can_submit(self, principal, user):
619
615
        return (self in principal.get_projects() and
620
 
                (late or not self.has_deadline_passed(user)))
 
616
                not self.has_deadline_passed(user))
621
617
 
622
 
    def submit(self, principal, path, revision, who, late=False):
 
618
    def submit(self, principal, path, revision, who):
623
619
        """Submit a Subversion path and revision to a project.
624
620
 
625
621
        @param principal: The owner of the Subversion repository, and the
627
623
        @param path: A path within that repository to submit.
628
624
        @param revision: The revision of that path to submit.
629
625
        @param who: The user who is actually making the submission.
630
 
        @param late: If True, will not raise a DeadlinePassed exception even
631
 
            after the deadline. (Default False.)
632
626
        """
633
627
 
634
 
        if not self.can_submit(principal, who, late=late):
 
628
        if not self.can_submit(principal, who):
635
629
            raise DeadlinePassed()
636
630
 
637
631
        a = Assessed.get(Store.of(self), principal, self)
740
734
            Semester.id == Offering.semester_id,
741
735
            (not active_only) or (Semester.state == u'current'))
742
736
 
743
 
    def get_svn_url(self, config):
 
737
    def get_svn_url(self, config, req):
744
738
        """Get the subversion repository URL for this user or group."""
745
 
        url = config['urls']['svn_addr']
 
739
        login = req.user.login
 
740
        url = urlparse.urlsplit(config['urls']['svn_addr'])
 
741
        url = urlparse.urlunsplit(url[:1] + (login+'@'+url[1],) + url[2:])
746
742
        path = 'groups/%s_%s_%s_%s' % (
747
743
                self.project_set.offering.subject.short_name,
748
744
                self.project_set.offering.semester.year,
749
 
                self.project_set.offering.semester.url_name,
 
745
                self.project_set.offering.semester.semester,
750
746
                self.name
751
747
                )
752
748
        return urlparse.urljoin(url, path)
867
863
    id = Int(name="extensionid", primary=True)
868
864
    assessed_id = Int(name="assessedid")
869
865
    assessed = Reference(assessed_id, Assessed.id)
870
 
    days = Int()
 
866
    deadline = DateTime()
871
867
    approver_id = Int(name="approver")
872
868
    approver = Reference(approver_id, User.id)
873
869
    notes = Unicode()
915
911
        return "/files/%s/%s/%s?r=%d" % (user.login,
916
912
            self.assessed.checkout_location, submitpath, self.revision)
917
913
 
918
 
    def get_svn_url(self, config):
919
 
        """Get subversion URL for this submission"""
920
 
        princ = self.assessed.principal
921
 
        base = princ.get_svn_url(config)
922
 
        if self.path.startswith(os.sep):
923
 
            return os.path.join(base,
924
 
                    urllib.quote(self.path[1:].encode('utf-8')))
925
 
        else:
926
 
            return os.path.join(base, urllib.quote(self.path.encode('utf-8')))
927
 
 
928
 
    def get_svn_export_command(self, req):
929
 
        """Returns a Unix shell command to export a submission"""
930
 
        svn_url = self.get_svn_url(req.config)
931
 
        _, ext = os.path.splitext(svn_url)
932
 
        username = (req.user.login if req.user.login.isalnum() else
933
 
                "'%s'"%req.user.login)
934
 
        # Export to a file or directory relative to the current directory,
935
 
        # with the student's login name, appended with the submitted file's
936
 
        # extension, if any
937
 
        export_path = self.assessed.principal.short_name + ext
938
 
        return "svn export --username %s -r%d '%s' %s"%(req.user.login,
939
 
                self.revision, svn_url, export_path)
940
 
 
941
914
    @staticmethod
942
915
    def test_and_normalise_path(path):
943
916
        """Test that path is valid, and normalise it. This prevents possible
957
930
            raise SubmissionError("Path must not contain '\\n', '[' or ']'")
958
931
        return os.path.normpath(path)
959
932
 
960
 
    @property
961
 
    def late(self):
962
 
        """True if the project was submitted late."""
963
 
        return self.days_late > 0
964
 
 
965
 
    @property
966
 
    def days_late(self):
967
 
        """The number of days the project was submitted late (rounded up), or
968
 
        0 if on-time."""
969
 
        # XXX: Need to respect extensions.
970
 
        return max(0,
971
 
            (self.date_submitted - self.assessed.project.deadline).days + 1)
972
 
 
973
933
# WORKSHEETS AND EXERCISES #
974
934
 
975
935
class Exercise(Storm):