38
39
'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
39
40
'Exercise', 'Worksheet', 'WorksheetExercise',
40
41
'ExerciseSave', 'ExerciseAttempt',
41
'TestCase', 'TestSuite', 'TestSuiteVar'
42
'AlreadyEnrolledError', 'TestCase', 'TestSuite', 'TestSuiteVar'
44
45
def _kwarg_init(self, **kwargs):
53
54
Returns the Storm connection string, generated from the conf file.
58
clusterstr += ivle.conf.db_user
59
if ivle.conf.db_password:
60
clusterstr += ':' + ivle.conf.db_password
63
host = ivle.conf.db_host or 'localhost'
64
port = ivle.conf.db_port or 5432
66
clusterstr += '%s:%d' % (host, port)
68
return "postgres://%s/%s" % (clusterstr, ivle.conf.db_dbname)
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,
98
88
studentid = Unicode()
99
89
settings = Unicode()
92
if self.rolenm is None:
94
return ivle.caps.Role(self.rolenm)
95
def _set_role(self, value):
96
if not isinstance(value, ivle.caps.Role):
97
raise TypeError("role must be an ivle.caps.Role")
98
self.rolenm = unicode(value)
99
role = property(_get_role, _set_role)
101
101
__init__ = _kwarg_init
103
103
def __repr__(self):
115
115
return self.hash_password(password) == self.passhash
117
def hasCap(self, capability):
118
"""Given a capability (which is a Role object), returns True if this
119
User has that capability, False otherwise.
121
return self.role.hasCap(capability)
118
124
def password_expired(self):
119
125
fieldval = self.pass_exp
195
201
return store.find(cls, cls.login == unicode(login)).one()
197
203
def get_permissions(self, user):
198
if user and user.admin or user is self:
204
if user and user.rolenm == 'admin' or user is self:
199
205
return set(['view', 'edit'])
232
238
id = Int(primary=True, name="semesterid")
234
240
semester = Unicode()
237
243
offerings = ReferenceSet(id, 'Offering.semester_id')
238
enrolments = ReferenceSet(id,
239
'Offering.semester_id',
241
'Enrolment.offering_id')
243
245
__init__ = _kwarg_init
263
265
project_sets = ReferenceSet(id, 'ProjectSet.offering_id')
265
worksheets = ReferenceSet(id,
266
'Worksheet.offering_id',
267
order_by="Worksheet.seq_no"
267
worksheets = ReferenceSet(id, 'Worksheet.offering_id')
270
269
__init__ = _kwarg_init
273
272
return "<%s %r in %r>" % (type(self).__name__, self.subject,
276
def enrol(self, user, role=u'student'):
275
def enrol(self, user):
277
276
'''Enrol a user in this offering.'''
278
enrolment = Store.of(self).find(Enrolment,
277
# We'll get a horrible database constraint violation error if we try
278
# to add a second enrolment.
279
if Store.of(self).find(Enrolment,
279
280
Enrolment.user_id == user.id,
280
Enrolment.offering_id == self.id).one()
282
if enrolment is None:
283
enrolment = Enrolment(user=user, offering=self)
284
self.enrolments.add(enrolment)
286
enrolment.active = True
287
enrolment.role = role
281
Enrolment.offering_id == self.id).count() == 1:
282
raise AlreadyEnrolledError()
284
e = Enrolment(user=user, offering=self, active=True)
285
self.enrolments.add(e)
289
287
def get_permissions(self, user):
291
289
if user is not None:
292
290
perms.add('view')
291
if user.rolenm == 'admin':
294
292
perms.add('edit')
396
396
# WORKSHEETS AND EXERCISES #
398
398
class Exercise(Storm):
399
__storm_table__ = "exercise"
399
# Note: Table "problem" is called "Exercise" in the Object layer, since
400
# it's called that everywhere else.
401
__storm_table__ = "problem"
402
#TODO: Add in a field for the user-friendly identifier
400
403
id = Unicode(primary=True, name="identifier")
402
405
description = Unicode()
418
421
def __repr__(self):
419
422
return "<%s %s>" % (type(self).__name__, self.name)
421
def get_permissions(self, user):
429
425
class Worksheet(Storm):
430
426
__storm_table__ = "worksheet"
432
428
id = Int(primary=True, name="worksheetid")
429
# XXX subject is not linked to a Subject object. This is a property of
430
# the database, and will be refactored.
433
431
offering_id = Int(name="offeringid")
434
identifier = Unicode()
432
name = Unicode(name="identifier")
436
433
assessable = Bool()
441
436
attempts = ReferenceSet(id, "ExerciseAttempt.worksheetid")
442
437
offering = Reference(offering_id, 'Offering.id')
444
all_worksheet_exercises = ReferenceSet(id,
439
exercises = ReferenceSet(id,
440
'WorksheetExercise.worksheet_id',
441
'WorksheetExercise.exercise_id',
443
# Use worksheet_exercises to get access to the WorksheetExercise objects
444
# binding worksheets to exercises. This is required to access the
446
worksheet_exercises = ReferenceSet(id,
445
447
'WorksheetExercise.worksheet_id')
447
# Use worksheet_exercises to get access to the *active* WorksheetExercise
448
# objects binding worksheets to exercises. This is required to access the
451
def worksheet_exercises(self):
452
return self.all_worksheet_exercises.find(active=True)
454
450
__init__ = _kwarg_init
481
477
return self.offering.get_permissions(user)
483
479
class WorksheetExercise(Storm):
484
__storm_table__ = "worksheet_exercise"
486
id = Int(primary=True, name="ws_ex_id")
480
__storm_table__ = "worksheet_problem"
481
__storm_primary__ = "worksheet_id", "exercise_id"
488
483
worksheet_id = Int(name="worksheetid")
489
484
worksheet = Reference(worksheet_id, Worksheet.id)
490
exercise_id = Unicode(name="exerciseid")
485
exercise_id = Unicode(name="problemid")
491
486
exercise = Reference(exercise_id, Exercise.id)
492
487
optional = Bool()
496
saves = ReferenceSet(id, "ExerciseSave.ws_ex_id")
497
attempts = ReferenceSet(id, "ExerciseAttempt.ws_ex_id")
499
489
__init__ = _kwarg_init
501
491
def __repr__(self):
502
492
return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
503
self.worksheet.identifier)
505
495
class ExerciseSave(Storm):
511
501
ExerciseSave may be extended with additional semantics (such as
512
502
ExerciseAttempt).
514
__storm_table__ = "exercise_save"
515
__storm_primary__ = "ws_ex_id", "user_id"
517
ws_ex_id = Int(name="ws_ex_id")
518
worksheet_exercise = Reference(ws_ex_id, "WorksheetExercise.id")
504
__storm_table__ = "problem_save"
505
__storm_primary__ = "exercise_id", "user_id", "date"
507
exercise_id = Unicode(name="problemid")
508
exercise = Reference(exercise_id, Exercise.id)
520
509
user_id = Int(name="loginid")
521
510
user = Reference(user_id, User.id)
522
511
date = DateTime()
514
worksheet = Reference(worksheetid, Worksheet.id)
525
516
__init__ = _kwarg_init
541
532
they won't count (either as a penalty or success), but will still be
544
__storm_table__ = "exercise_attempt"
545
__storm_primary__ = "ws_ex_id", "user_id", "date"
535
__storm_table__ = "problem_attempt"
536
__storm_primary__ = "exercise_id", "user_id", "date"
547
538
# The "text" field is the same but has a different name in the DB table
548
539
# for some reason.
590
581
class TestSuiteVar(Storm):
591
582
"""A container for the arguments of a Test Suite"""
592
__storm_table__ = "suite_variable"
583
__storm_table__ = "suite_variables"
593
584
__storm_primary__ = "varid"
606
597
class TestCasePart(Storm):
607
598
"""A container for the test elements of a Test Case"""
608
__storm_table__ = "test_case_part"
599
__storm_table__ = "test_case_parts"
609
600
__storm_primary__ = "partid"