30
30
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
31
31
Reference, ReferenceSet, Bool, Storm, Desc
32
from storm.exceptions import NotOneError, IntegrityError
35
from ivle.worksheet.rst import rst
35
37
__all__ = ['get_store',
37
39
'Subject', 'Semester', 'Offering', 'Enrolment',
38
40
'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
41
'Assessed', 'ProjectSubmission', 'ProjectExtension',
39
42
'Exercise', 'Worksheet', 'WorksheetExercise',
40
43
'ExerciseSave', 'ExerciseAttempt',
41
44
'TestCase', 'TestSuite', 'TestSuiteVar'
197
200
def get_permissions(self, user):
198
201
if user and user.admin or user is self:
199
return set(['view', 'edit'])
202
return set(['view', 'edit', 'submit_project'])
282
289
enrolment.active = True
283
290
enrolment.role = role
292
def unenrol(self, user):
293
'''Unenrol a user from this offering.'''
294
enrolment = Store.of(self).find(Enrolment,
295
Enrolment.user_id == user.id,
296
Enrolment.offering_id == self.id).one()
297
Store.of(enrolment).remove(enrolment)
285
299
def get_permissions(self, user):
287
301
if user is not None:
302
enrolment = self.get_enrolment(user)
303
if enrolment or user.admin:
305
if (enrolment and enrolment.role in (u'tutor', u'lecturer')) \
290
307
perms.add('edit')
310
def get_enrolment(self, user):
312
enrolment = self.enrolments.find(user=user).one()
293
318
class Enrolment(Storm):
294
319
__storm_table__ = "enrolment"
295
320
__storm_primary__ = "user_id", "offering_id"
339
364
__storm_table__ = "project"
341
366
id = Int(name="projectid", primary=True)
368
short_name = Unicode()
342
369
synopsis = Unicode()
344
371
project_set_id = Int(name="projectsetid")
345
372
project_set = Reference(project_set_id, ProjectSet.id)
346
373
deadline = DateTime()
375
assesseds = ReferenceSet(id, 'Assessed.project_id')
376
submissions = ReferenceSet(id,
377
'Assessed.project_id',
379
'ProjectSubmission.assessed_id')
348
381
__init__ = _kwarg_init
350
383
def __repr__(self):
351
return "<%s '%s' in %r>" % (type(self).__name__, self.synopsis,
384
return "<%s '%s' in %r>" % (type(self).__name__, self.short_name,
352
385
self.project_set.offering)
354
387
class ProjectGroup(Storm):
374
407
return "<%s %s in %r>" % (type(self).__name__, self.name,
375
408
self.project_set.offering)
410
def get_permissions(self, user):
411
if user.admin or user in self.members:
412
return set(['submit_project'])
377
416
class ProjectGroupMembership(Storm):
378
417
__storm_table__ = "group_member"
379
418
__storm_primary__ = "user_id", "project_group_id"
389
428
return "<%s %r in %r>" % (type(self).__name__, self.user,
390
429
self.project_group)
431
class Assessed(Storm):
432
__storm_table__ = "assessed"
434
id = Int(name="assessedid", primary=True)
435
user_id = Int(name="loginid")
436
user = Reference(user_id, User.id)
437
project_group_id = Int(name="groupid")
438
project_group = Reference(project_group_id, ProjectGroup.id)
440
project_id = Int(name="projectid")
441
project = Reference(project_id, Project.id)
443
extensions = ReferenceSet(id, 'ProjectExtension.assessed_id')
444
submissions = ReferenceSet(id, 'ProjectSubmission.assessed_id')
447
return "<%s %r in %r>" % (type(self).__name__,
448
self.user or self.project_group, self.project)
450
class ProjectExtension(Storm):
451
__storm_table__ = "project_extension"
453
id = Int(name="extensionid", primary=True)
454
assessed_id = Int(name="assessedid")
455
assessed = Reference(assessed_id, Assessed.id)
456
deadline = DateTime()
457
approver_id = Int(name="approver")
458
approver = Reference(approver_id, User.id)
461
class ProjectSubmission(Storm):
462
__storm_table__ = "project_submission"
464
id = Int(name="submissionid", primary=True)
465
assessed_id = Int(name="assessedid")
466
assessed = Reference(assessed_id, Assessed.id)
469
date_submitted = DateTime()
392
472
# WORKSHEETS AND EXERCISES #
394
474
class Exercise(Storm):
401
481
include = Unicode()
484
worksheet_exercises = ReferenceSet(id,
485
'WorksheetExercise.exercise_id')
404
487
worksheets = ReferenceSet(id,
405
488
'WorksheetExercise.exercise_id',
406
489
'WorksheetExercise.worksheet_id',
410
test_suites = ReferenceSet(id, 'TestSuite.exercise_id')
493
test_suites = ReferenceSet(id,
494
'TestSuite.exercise_id',
412
497
__init__ = _kwarg_init
417
502
def get_permissions(self, user):
419
505
if user is not None:
421
507
perms.add('edit')
422
508
perms.add('view')
509
elif 'lecturer' in set((e.role for e in user.active_enrolments)):
515
def get_description(self):
516
return rst(self.description)
519
"""Deletes the exercise, providing it has no associated worksheets."""
520
if (self.worksheet_exercises.count() > 0):
521
raise IntegrityError()
522
for suite in self.test_suites:
524
Store.of(self).remove(self)
425
526
class Worksheet(Storm):
426
527
__storm_table__ = "worksheet"
443
544
# Use worksheet_exercises to get access to the *active* WorksheetExercise
444
545
# objects binding worksheets to exercises. This is required to access the
445
546
# "optional" field.
447
549
def worksheet_exercises(self):
448
550
return self.all_worksheet_exercises.find(active=True)
464
566
return store.find(cls, cls.subject == unicode(subjectname),
465
567
cls.name == unicode(worksheetname)).one()
467
def remove_all_exercises(self, store):
569
def remove_all_exercises(self):
469
571
Remove all exercises from this worksheet.
470
572
This does not delete the exercises themselves. It just removes them
471
573
from the worksheet.
575
store = Store.of(self)
576
for ws_ex in self.all_worksheet_exercises:
577
if ws_ex.saves.count() > 0 or ws_ex.attempts.count() > 0:
578
raise IntegrityError()
473
579
store.find(WorksheetExercise,
474
580
WorksheetExercise.worksheet == self).remove()
476
582
def get_permissions(self, user):
477
583
return self.offering.get_permissions(user)
586
"""Returns the xml of this worksheet, converts from rst if required."""
587
if self.format == u'rst':
588
ws_xml = rst(self.data)
594
"""Deletes the worksheet, provided it has no attempts on any exercises.
596
Returns True if delete succeeded, or False if this worksheet has
597
attempts attached."""
598
for ws_ex in self.all_worksheet_exercises:
599
if ws_ex.saves.count() > 0 or ws_ex.attempts.count() > 0:
600
raise IntegrityError()
602
self.remove_all_exercises()
603
Store.of(self).remove(self)
479
605
class WorksheetExercise(Storm):
480
606
__storm_table__ = "worksheet_exercise"
498
624
return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
499
625
self.worksheet.identifier)
627
def get_permissions(self, user):
628
return self.worksheet.get_permissions(user)
501
631
class ExerciseSave(Storm):
503
633
Represents a potential solution to an exercise that a user has submitted
561
691
function = Unicode()
562
692
stdin = Unicode()
563
693
exercise = Reference(exercise_id, Exercise.id)
564
test_cases = ReferenceSet(suiteid, 'TestCase.suiteid')
565
variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid')
694
test_cases = ReferenceSet(suiteid, 'TestCase.suiteid', order_by="seq_no")
695
variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid', order_by='arg_no')
698
"""Delete this suite, without asking questions."""
699
for vaariable in self.variables:
701
for test_case in self.test_cases:
703
Store.of(self).remove(self)
567
705
class TestCase(Storm):
568
706
"""A TestCase is a member of a TestSuite.
582
720
parts = ReferenceSet(testid, "TestCasePart.testid")
584
722
__init__ = _kwarg_init
725
for part in self.parts:
727
Store.of(self).remove(self)
586
729
class TestSuiteVar(Storm):
587
730
"""A container for the arguments of a Test Suite"""