39
39
'Subject', 'Semester', 'Offering', 'Enrolment',
40
40
'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
41
'Assessed', 'ProjectSubmission', 'ProjectExtension',
41
42
'Exercise', 'Worksheet', 'WorksheetExercise',
42
43
'ExerciseSave', 'ExerciseAttempt',
43
44
'TestCase', 'TestSuite', 'TestSuiteVar'
184
189
'''A sanely ordered list of all of the user's enrolments.'''
185
190
return self._get_enrolments(False)
192
def get_projects(self, offering=None, active_only=True):
193
'''Return Projects that the user can submit.
195
This will include projects for offerings in which the user is
196
enrolled, as long as the project is not in a project set which has
197
groups (ie. if maximum number of group members is 0).
199
Unless active_only is False, only projects for active offerings will
202
If an offering is specified, returned projects will be limited to
203
those for that offering.
205
return Store.of(self).find(Project,
206
Project.project_set_id == ProjectSet.id,
207
ProjectSet.max_students_per_group == None,
208
ProjectSet.offering_id == Offering.id,
209
(offering is None) or (Offering.id == offering.id),
210
Semester.id == Offering.semester_id,
211
(not active_only) or (Semester.state == u'current'),
212
Enrolment.offering_id == Offering.id,
213
Enrolment.user_id == self.id)
188
216
def hash_password(password):
189
217
return md5.md5(password).hexdigest()
363
391
__storm_table__ = "project"
365
393
id = Int(name="projectid", primary=True)
395
short_name = Unicode()
366
396
synopsis = Unicode()
368
398
project_set_id = Int(name="projectsetid")
369
399
project_set = Reference(project_set_id, ProjectSet.id)
370
400
deadline = DateTime()
402
assesseds = ReferenceSet(id, 'Assessed.project_id')
403
submissions = ReferenceSet(id,
404
'Assessed.project_id',
406
'ProjectSubmission.assessed_id')
372
408
__init__ = _kwarg_init
374
410
def __repr__(self):
375
return "<%s '%s' in %r>" % (type(self).__name__, self.synopsis,
411
return "<%s '%s' in %r>" % (type(self).__name__, self.short_name,
376
412
self.project_set.offering)
414
def can_submit(self, principal):
415
return (self in principal.get_projects() and
416
self.deadline > datetime.datetime.now())
418
def submit(self, principal, path, revision, who):
419
"""Submit a Subversion path and revision to a project.
421
'principal' is the owner of the Subversion repository, and the
422
entity on behalf of whom the submission is being made. 'path' is
423
a path within that repository, and 'revision' specifies which
424
revision of that path. 'who' is the person making the submission.
427
if not self.can_submit(principal):
428
raise Exception('cannot submit')
430
a = Assessed.get(Store.of(self), principal, self)
431
ps = ProjectSubmission()
433
ps.revision = revision
434
ps.date_submitted = datetime.datetime.now()
378
441
class ProjectGroup(Storm):
379
442
__storm_table__ = "project_group"
398
461
return "<%s %s in %r>" % (type(self).__name__, self.name,
399
462
self.project_set.offering)
465
def display_name(self):
466
return '%s (%s)' % (self.nick, self.name)
468
def get_projects(self, offering=None, active_only=True):
469
'''Return Projects that the group can submit.
471
This will include projects in the project set which owns this group,
472
unless the project set disallows groups (in which case none will be
475
Unless active_only is False, projects will only be returned if the
476
group's offering is active.
478
If an offering is specified, projects will only be returned if it
481
return Store.of(self).find(Project,
482
Project.project_set_id == ProjectSet.id,
483
ProjectSet.id == self.project_set.id,
484
ProjectSet.max_students_per_group != None,
485
ProjectSet.offering_id == Offering.id,
486
(offering is None) or (Offering.id == offering.id),
487
Semester.id == Offering.semester_id,
488
(not active_only) or (Semester.state == u'current'))
491
def get_permissions(self, user):
492
if user.admin or user in self.members:
493
return set(['submit_project'])
401
497
class ProjectGroupMembership(Storm):
402
498
__storm_table__ = "group_member"
403
499
__storm_primary__ = "user_id", "project_group_id"
413
509
return "<%s %r in %r>" % (type(self).__name__, self.user,
414
510
self.project_group)
512
class Assessed(Storm):
513
__storm_table__ = "assessed"
515
id = Int(name="assessedid", primary=True)
516
user_id = Int(name="loginid")
517
user = Reference(user_id, User.id)
518
project_group_id = Int(name="groupid")
519
project_group = Reference(project_group_id, ProjectGroup.id)
521
project_id = Int(name="projectid")
522
project = Reference(project_id, Project.id)
524
extensions = ReferenceSet(id, 'ProjectExtension.assessed_id')
525
submissions = ReferenceSet(id, 'ProjectSubmission.assessed_id')
528
return "<%s %r in %r>" % (type(self).__name__,
529
self.user or self.project_group, self.project)
532
def get(cls, store, principal, project):
534
if t not in (User, ProjectGroup):
535
raise AssertionError('principal must be User or ProjectGroup')
538
(t is User) or (cls.project_group_id == principal.id),
539
(t is ProjectGroup) or (cls.user_id == principal.id),
540
Project.id == project.id).one()
547
a.project_group = principal
554
class ProjectExtension(Storm):
555
__storm_table__ = "project_extension"
557
id = Int(name="extensionid", primary=True)
558
assessed_id = Int(name="assessedid")
559
assessed = Reference(assessed_id, Assessed.id)
560
deadline = DateTime()
561
approver_id = Int(name="approver")
562
approver = Reference(approver_id, User.id)
565
class ProjectSubmission(Storm):
566
__storm_table__ = "project_submission"
568
id = Int(name="submissionid", primary=True)
569
assessed_id = Int(name="assessedid")
570
assessed = Reference(assessed_id, Assessed.id)
573
submitter_id = Int(name="submitter")
574
submitter = Reference(submitter_id, User.id)
575
date_submitted = DateTime()
416
578
# WORKSHEETS AND EXERCISES #
418
580
class Exercise(Storm):