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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
            'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
40
40
            'Exercise', 'Worksheet', 'WorksheetExercise',
41
41
            'ExerciseSave', 'ExerciseAttempt',
42
 
            'AlreadyEnrolledError'
 
42
            'AlreadyEnrolledError', 'TestCase', 'TestSuite', 'TestSuiteVar'
43
43
        ]
44
44
 
45
45
def _kwarg_init(self, **kwargs):
53
53
    """
54
54
    Returns the Storm connection string, generated from the conf file.
55
55
    """
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,
58
 
        ivle.conf.db_dbname)
 
56
 
 
57
    clusterstr = ''
 
58
    if ivle.conf.db_user:
 
59
        clusterstr += ivle.conf.db_user
 
60
        if ivle.conf.db_password:
 
61
            clusterstr += ':' + ivle.conf.db_password
 
62
        clusterstr += '@'
 
63
 
 
64
    host = ivle.conf.db_host or 'localhost'
 
65
    port = ivle.conf.db_port or 5432
 
66
 
 
67
    clusterstr += '%s:%d' % (host, port)
 
68
 
 
69
    return "postgres://%s/%s" % (clusterstr, ivle.conf.db_dbname)
59
70
 
60
71
def get_store():
61
72
    """
130
141
        fieldval = self.acct_exp
131
142
        return fieldval is not None and datetime.datetime.now() > fieldval
132
143
 
 
144
    @property
 
145
    def valid(self):
 
146
        return self.state == 'enabled' and not self.account_expired
 
147
 
133
148
    def _get_enrolments(self, justactive):
134
149
        return Store.of(self).find(Enrolment,
135
150
            Enrolment.user_id == self.id,
196
211
        """
197
212
        return store.find(cls, cls.login == unicode(login)).one()
198
213
 
 
214
    def get_permissions(self, user):
 
215
        if user and user.rolenm == 'admin' or user is self:
 
216
            return set(['view', 'edit'])
 
217
        else:
 
218
            return set()
 
219
 
199
220
# SUBJECTS AND ENROLMENTS #
200
221
 
201
222
class Subject(Storm):
214
235
    def __repr__(self):
215
236
        return "<%s '%s'>" % (type(self).__name__, self.short_name)
216
237
 
 
238
    def get_permissions(self, user):
 
239
        perms = set()
 
240
        if user is not None:
 
241
            perms.add('view')
 
242
            if user.rolenm == 'admin':
 
243
                perms.add('edit')
 
244
        return perms
 
245
 
217
246
class Semester(Storm):
218
247
    __storm_table__ = "semester"
219
248
 
246
275
                           'User.id')
247
276
    project_sets = ReferenceSet(id, 'ProjectSet.offering_id')
248
277
 
 
278
    worksheets = ReferenceSet(id, 
 
279
        'Worksheet.offering_id', 
 
280
        order_by="Worksheet.seq_no"
 
281
    )
 
282
 
249
283
    __init__ = _kwarg_init
250
284
 
251
285
    def __repr__(self):
264
298
        e = Enrolment(user=user, offering=self, active=True)
265
299
        self.enrolments.add(e)
266
300
 
 
301
    def get_permissions(self, user):
 
302
        perms = set()
 
303
        if user is not None:
 
304
            perms.add('view')
 
305
            if user.rolenm in ('admin', 'lecturer'):
 
306
                perms.add('edit')
 
307
        return perms
 
308
 
267
309
class Enrolment(Storm):
268
310
    __storm_table__ = "enrolment"
269
311
    __storm_primary__ = "user_id", "offering_id"
368
410
# WORKSHEETS AND EXERCISES #
369
411
 
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"
374
 
 
375
 
    id = Int(primary=True, name="problemid")
376
 
    name = Unicode(name="identifier")
377
 
    spec = Unicode()
 
413
    __storm_table__ = "exercise"
 
414
    id = Unicode(primary=True, name="identifier")
 
415
    name = Unicode()
 
416
    description = Unicode()
 
417
    partial = Unicode()
 
418
    solution = Unicode()
 
419
    include = Unicode()
 
420
    num_rows = Int()
378
421
 
379
422
    worksheets = ReferenceSet(id,
380
423
        'WorksheetExercise.exercise_id',
381
424
        'WorksheetExercise.worksheet_id',
382
425
        'Worksheet.id'
383
426
    )
 
427
    
 
428
    test_suites = ReferenceSet(id, 'TestSuite.exercise_id')
384
429
 
385
430
    __init__ = _kwarg_init
386
431
 
387
432
    def __repr__(self):
388
433
        return "<%s %s>" % (type(self).__name__, self.name)
389
434
 
390
 
    @classmethod
391
 
    def get_by_name(cls, store, name):
392
 
        """
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
395
 
        automatically.
396
 
        """
397
 
        ex = store.find(cls, cls.name == unicode(name)).one()
398
 
        if ex is not None:
399
 
            return ex
400
 
        ex = Exercise(name=unicode(name))
401
 
        store.add(ex)
402
 
        store.commit()
403
 
        return ex
 
435
    def get_permissions(self, user):
 
436
        perms = set()
 
437
        if user is not None:
 
438
            if user.rolenm in ('admin', 'lecturer'):
 
439
                perms.add('edit')
 
440
                perms.add('view')
 
441
        return perms
404
442
 
405
443
class Worksheet(Storm):
406
444
    __storm_table__ = "worksheet"
407
445
 
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.
411
 
    subject = Unicode()
412
 
    name = Unicode(name="identifier")
 
447
    offering_id = Int(name="offeringid")
 
448
    identifier = Unicode()
 
449
    name = Unicode()
413
450
    assessable = Bool()
414
 
    mtime = DateTime()
415
 
 
416
 
    exercises = ReferenceSet(id,
417
 
        'WorksheetExercise.worksheet_id',
418
 
        'WorksheetExercise.exercise_id',
419
 
        Exercise.id)
 
451
    data = Unicode()
 
452
    seq_no = Int()
 
453
    format = Unicode()
 
454
 
 
455
    attempts = ReferenceSet(id, "ExerciseAttempt.worksheetid")
 
456
    offering = Reference(offering_id, 'Offering.id')
 
457
 
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')
 
463
        
425
464
 
426
465
    __init__ = _kwarg_init
427
466
 
448
487
        """
449
488
        store.find(WorksheetExercise,
450
489
            WorksheetExercise.worksheet == self).remove()
 
490
            
 
491
    def get_permissions(self, user):
 
492
        return self.offering.get_permissions(user)
451
493
 
452
494
class WorksheetExercise(Storm):
453
 
    __storm_table__ = "worksheet_problem"
454
 
    __storm_primary__ = "worksheet_id", "exercise_id"
 
495
    __storm_table__ = "worksheet_exercise"
 
496
    
 
497
    id = Int(primary=True, name="ws_ex_id")
455
498
 
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()
 
504
    active = Bool()
 
505
    seq_no = Int()
 
506
    
 
507
    saves = ReferenceSet(id, "ExerciseSave.ws_ex_id")
 
508
    attempts = ReferenceSet(id, "ExerciseAttempt.ws_ex_id")
461
509
 
462
510
    __init__ = _kwarg_init
463
511
 
464
512
    def __repr__(self):
465
513
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
466
 
                                  self.worksheet.name)
 
514
                                  self.worksheet.identifier)
467
515
 
468
516
class ExerciseSave(Storm):
469
517
    """
474
522
    ExerciseSave may be extended with additional semantics (such as
475
523
    ExerciseAttempt).
476
524
    """
477
 
    __storm_table__ = "problem_save"
478
 
    __storm_primary__ = "exercise_id", "user_id", "date"
479
 
 
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"
 
527
 
 
528
    ws_ex_id = Int(name="ws_ex_id")
 
529
    worksheet_exercise = Reference(ws_ex_id, "WorksheetExercise.id")
 
530
 
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
504
553
        stored.
505
554
    """
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"
508
557
 
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()
513
562
    active = Bool()
 
563
    
 
564
    def get_permissions(self, user):
 
565
        return set(['view']) if user is self.user else set()
 
566
  
 
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"
 
571
    
 
572
    suiteid = Int()
 
573
    exercise_id = Unicode(name="exerciseid")
 
574
    description = Unicode()
 
575
    seq_no = Int()
 
576
    function = Unicode()
 
577
    stdin = Unicode()
 
578
    exercise = Reference(exercise_id, Exercise.id)
 
579
    test_cases = ReferenceSet(suiteid, 'TestCase.suiteid')
 
580
    variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid')
 
581
 
 
582
class TestCase(Storm):
 
583
    """A TestCase is a member of a TestSuite.
 
584
    
 
585
    It contains the data necessary to check if an exercise is correct"""
 
586
    __storm_table__ = "test_case"
 
587
    __storm_primary__ = "testid", "suiteid"
 
588
    
 
589
    testid = Int()
 
590
    suiteid = Int()
 
591
    suite = Reference(suiteid, "TestSuite.suiteid")
 
592
    passmsg = Unicode()
 
593
    failmsg = Unicode()
 
594
    test_default = Unicode()
 
595
    seq_no = Int()
 
596
    
 
597
    parts = ReferenceSet(testid, "TestCasePart.testid")
 
598
    
 
599
    __init__ = _kwarg_init
 
600
 
 
601
class TestSuiteVar(Storm):
 
602
    """A container for the arguments of a Test Suite"""
 
603
    __storm_table__ = "suite_variable"
 
604
    __storm_primary__ = "varid"
 
605
    
 
606
    varid = Int()
 
607
    suiteid = Int()
 
608
    var_name = Unicode()
 
609
    var_value = Unicode()
 
610
    var_type = Unicode()
 
611
    arg_no = Int()
 
612
    
 
613
    suite = Reference(suiteid, "TestSuite.suiteid")
 
614
    
 
615
    __init__ = _kwarg_init
 
616
    
 
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"
 
621
    
 
622
    partid = Int()
 
623
    testid = Int()
 
624
    
 
625
    part_type = Unicode()
 
626
    test_type = Unicode()
 
627
    data = Unicode()
 
628
    filename = Unicode()
 
629
    
 
630
    test = Reference(testid, "TestCase.testid")
 
631
    
 
632
    __init__ = _kwarg_init