39
39
'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
40
40
'Exercise', 'Worksheet', 'WorksheetExercise',
41
41
'ExerciseSave', 'ExerciseAttempt',
42
'AlreadyEnrolledError'
42
'AlreadyEnrolledError', 'TestCase', 'TestSuite', 'TestSuiteVar'
45
45
def _kwarg_init(self, **kwargs):
54
54
Returns the Storm connection string, generated from the conf file.
56
return "postgres://%s:%s@%s:%d/%s" % (ivle.conf.db_user,
57
ivle.conf.db_password, ivle.conf.db_host, ivle.conf.db_port,
59
clusterstr += ivle.conf.db_user
60
if ivle.conf.db_password:
61
clusterstr += ':' + ivle.conf.db_password
64
host = ivle.conf.db_host or 'localhost'
65
port = ivle.conf.db_port or 5432
67
clusterstr += '%s:%d' % (host, port)
69
return "postgres://%s/%s" % (clusterstr, ivle.conf.db_dbname)
130
141
fieldval = self.acct_exp
131
142
return fieldval is not None and datetime.datetime.now() > fieldval
146
return self.state == 'enabled' and not self.account_expired
133
148
def _get_enrolments(self, justactive):
134
149
return Store.of(self).find(Enrolment,
135
150
Enrolment.user_id == self.id,
197
212
return store.find(cls, cls.login == unicode(login)).one()
214
def get_permissions(self, user):
215
if user and user.rolenm == 'admin' or user is self:
216
return set(['view', 'edit'])
199
220
# SUBJECTS AND ENROLMENTS #
201
222
class Subject(Storm):
264
298
e = Enrolment(user=user, offering=self, active=True)
265
299
self.enrolments.add(e)
301
def get_permissions(self, user):
305
if user.rolenm in ('admin', 'lecturer'):
267
309
class Enrolment(Storm):
268
310
__storm_table__ = "enrolment"
269
311
__storm_primary__ = "user_id", "offering_id"
368
410
# WORKSHEETS AND EXERCISES #
370
412
class Exercise(Storm):
371
# Note: Table "problem" is called "Exercise" in the Object layer, since
372
# it's called that everywhere else.
373
__storm_table__ = "problem"
375
id = Int(primary=True, name="problemid")
376
name = Unicode(name="identifier")
413
__storm_table__ = "exercise"
414
id = Unicode(primary=True, name="identifier")
416
description = Unicode()
379
422
worksheets = ReferenceSet(id,
380
423
'WorksheetExercise.exercise_id',
381
424
'WorksheetExercise.worksheet_id',
428
test_suites = ReferenceSet(id, 'TestSuite.exercise_id')
385
430
__init__ = _kwarg_init
387
432
def __repr__(self):
388
433
return "<%s %s>" % (type(self).__name__, self.name)
391
def get_by_name(cls, store, name):
393
Get the Exercise from the db associated with a given store and name.
394
If the exercise is not in the database, creates it and inserts it
397
ex = store.find(cls, cls.name == unicode(name)).one()
400
ex = Exercise(name=unicode(name))
435
def get_permissions(self, user):
438
if user.rolenm in ('admin', 'lecturer'):
405
443
class Worksheet(Storm):
406
444
__storm_table__ = "worksheet"
408
446
id = Int(primary=True, name="worksheetid")
409
# XXX subject is not linked to a Subject object. This is a property of
410
# the database, and will be refactored.
412
name = Unicode(name="identifier")
447
offering_id = Int(name="offeringid")
448
identifier = Unicode()
413
450
assessable = Bool()
416
exercises = ReferenceSet(id,
417
'WorksheetExercise.worksheet_id',
418
'WorksheetExercise.exercise_id',
455
attempts = ReferenceSet(id, "ExerciseAttempt.worksheetid")
456
offering = Reference(offering_id, 'Offering.id')
420
458
# Use worksheet_exercises to get access to the WorksheetExercise objects
421
459
# binding worksheets to exercises. This is required to access the
422
460
# "optional" field.
423
461
worksheet_exercises = ReferenceSet(id,
424
462
'WorksheetExercise.worksheet_id')
426
465
__init__ = _kwarg_init
449
488
store.find(WorksheetExercise,
450
489
WorksheetExercise.worksheet == self).remove()
491
def get_permissions(self, user):
492
return self.offering.get_permissions(user)
452
494
class WorksheetExercise(Storm):
453
__storm_table__ = "worksheet_problem"
454
__storm_primary__ = "worksheet_id", "exercise_id"
495
__storm_table__ = "worksheet_exercise"
497
id = Int(primary=True, name="ws_ex_id")
456
499
worksheet_id = Int(name="worksheetid")
457
500
worksheet = Reference(worksheet_id, Worksheet.id)
458
exercise_id = Int(name="problemid")
501
exercise_id = Unicode(name="exerciseid")
459
502
exercise = Reference(exercise_id, Exercise.id)
460
503
optional = Bool()
507
saves = ReferenceSet(id, "ExerciseSave.ws_ex_id")
508
attempts = ReferenceSet(id, "ExerciseAttempt.ws_ex_id")
462
510
__init__ = _kwarg_init
464
512
def __repr__(self):
465
513
return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
514
self.worksheet.identifier)
468
516
class ExerciseSave(Storm):
474
522
ExerciseSave may be extended with additional semantics (such as
475
523
ExerciseAttempt).
477
__storm_table__ = "problem_save"
478
__storm_primary__ = "exercise_id", "user_id", "date"
480
exercise_id = Int(name="problemid")
481
exercise = Reference(exercise_id, Exercise.id)
525
__storm_table__ = "exercise_save"
526
__storm_primary__ = "ws_ex_id", "user_id"
528
ws_ex_id = Int(name="ws_ex_id")
529
worksheet_exercise = Reference(ws_ex_id, "WorksheetExercise.id")
482
531
user_id = Int(name="loginid")
483
532
user = Reference(user_id, User.id)
484
533
date = DateTime()
503
552
they won't count (either as a penalty or success), but will still be
506
__storm_table__ = "problem_attempt"
507
__storm_primary__ = "exercise_id", "user_id", "date"
555
__storm_table__ = "exercise_attempt"
556
__storm_primary__ = "ws_ex_id", "user_id", "date"
509
558
# The "text" field is the same but has a different name in the DB table
510
559
# for some reason.
511
560
text = Unicode(name="attempt")
512
561
complete = Bool()
564
def get_permissions(self, user):
565
return set(['view']) if user is self.user else set()
567
class TestSuite(Storm):
568
"""A Testsuite acts as a container for the test cases of an exercise."""
569
__storm_table__ = "test_suite"
570
__storm_primary__ = "exercise_id", "suiteid"
573
exercise_id = Unicode(name="exerciseid")
574
description = Unicode()
578
exercise = Reference(exercise_id, Exercise.id)
579
test_cases = ReferenceSet(suiteid, 'TestCase.suiteid')
580
variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid')
582
class TestCase(Storm):
583
"""A TestCase is a member of a TestSuite.
585
It contains the data necessary to check if an exercise is correct"""
586
__storm_table__ = "test_case"
587
__storm_primary__ = "testid", "suiteid"
591
suite = Reference(suiteid, "TestSuite.suiteid")
594
test_default = Unicode()
597
parts = ReferenceSet(testid, "TestCasePart.testid")
599
__init__ = _kwarg_init
601
class TestSuiteVar(Storm):
602
"""A container for the arguments of a Test Suite"""
603
__storm_table__ = "suite_variable"
604
__storm_primary__ = "varid"
609
var_value = Unicode()
613
suite = Reference(suiteid, "TestSuite.suiteid")
615
__init__ = _kwarg_init
617
class TestCasePart(Storm):
618
"""A container for the test elements of a Test Case"""
619
__storm_table__ = "test_case_part"
620
__storm_primary__ = "partid"
625
part_type = Unicode()
626
test_type = Unicode()
630
test = Reference(testid, "TestCase.testid")
632
__init__ = _kwarg_init