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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: William Grant
  • Date: 2009-03-26 05:33:03 UTC
  • mto: (1165.3.1 submissions)
  • mto: This revision was merged to the branch mainline in revision 1174.
  • Revision ID: grantw@unimelb.edu.au-20090326053303-t1wsjswhk2sl2gml
Start a submission UI in ivle.webapp.submit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
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
32
33
 
33
34
import ivle.conf
 
35
from ivle.worksheet.rst import rst
34
36
 
35
37
__all__ = ['get_store',
36
38
            'User',
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'
196
199
 
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'])
200
203
        else:
201
204
            return set()
202
205
 
235
238
    state = Unicode()
236
239
 
237
240
    offerings = ReferenceSet(id, 'Offering.semester_id')
 
241
    enrolments = ReferenceSet(id,
 
242
                              'Offering.semester_id',
 
243
                              'Offering.id',
 
244
                              'Enrolment.offering_id')
238
245
 
239
246
    __init__ = _kwarg_init
240
247
 
260
267
 
261
268
    worksheets = ReferenceSet(id, 
262
269
        'Worksheet.offering_id', 
263
 
        order_by="Worksheet.seq_no"
 
270
        order_by="seq_no"
264
271
    )
265
272
 
266
273
    __init__ = _kwarg_init
282
289
        enrolment.active = True
283
290
        enrolment.role = role
284
291
 
 
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)
 
298
 
285
299
    def get_permissions(self, user):
286
300
        perms = set()
287
301
        if user is not None:
288
 
            perms.add('view')
289
 
            if user.admin:
 
302
            enrolment = self.get_enrolment(user)
 
303
            if enrolment or user.admin:
 
304
                perms.add('view')
 
305
            if (enrolment and enrolment.role in (u'tutor', u'lecturer')) \
 
306
               or user.admin:
290
307
                perms.add('edit')
291
308
        return perms
292
309
 
 
310
    def get_enrolment(self, user):
 
311
        try:
 
312
            enrolment = self.enrolments.find(user=user).one()
 
313
        except NotOneError:
 
314
            enrolment = None
 
315
 
 
316
        return enrolment
 
317
 
293
318
class Enrolment(Storm):
294
319
    __storm_table__ = "enrolment"
295
320
    __storm_primary__ = "user_id", "offering_id"
339
364
    __storm_table__ = "project"
340
365
 
341
366
    id = Int(name="projectid", primary=True)
 
367
    name = Unicode()
 
368
    short_name = Unicode()
342
369
    synopsis = Unicode()
343
370
    url = Unicode()
344
371
    project_set_id = Int(name="projectsetid")
345
372
    project_set = Reference(project_set_id, ProjectSet.id)
346
373
    deadline = DateTime()
347
374
 
 
375
    assesseds = ReferenceSet(id, 'Assessed.project_id')
 
376
    submissions = ReferenceSet(id,
 
377
                               'Assessed.project_id',
 
378
                               'Assessed.id',
 
379
                               'ProjectSubmission.assessed_id')
 
380
 
348
381
    __init__ = _kwarg_init
349
382
 
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)
353
386
 
354
387
class ProjectGroup(Storm):
374
407
        return "<%s %s in %r>" % (type(self).__name__, self.name,
375
408
                                  self.project_set.offering)
376
409
 
 
410
    def get_permissions(self, user):
 
411
        if user.admin or user in self.members:
 
412
            return set(['submit_project'])
 
413
        else:
 
414
            return set()
 
415
 
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)
391
430
 
 
431
class Assessed(Storm):
 
432
    __storm_table__ = "assessed"
 
433
 
 
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)
 
439
 
 
440
    project_id = Int(name="projectid")
 
441
    project = Reference(project_id, Project.id)
 
442
 
 
443
    extensions = ReferenceSet(id, 'ProjectExtension.assessed_id')
 
444
    submissions = ReferenceSet(id, 'ProjectSubmission.assessed_id')
 
445
 
 
446
    def __repr__(self):
 
447
        return "<%s %r in %r>" % (type(self).__name__,
 
448
            self.user or self.project_group, self.project)
 
449
 
 
450
class ProjectExtension(Storm):
 
451
    __storm_table__ = "project_extension"
 
452
 
 
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)
 
459
    notes = Unicode()
 
460
 
 
461
class ProjectSubmission(Storm):
 
462
    __storm_table__ = "project_submission"
 
463
 
 
464
    id = Int(name="submissionid", primary=True)
 
465
    assessed_id = Int(name="assessedid")
 
466
    assessed = Reference(assessed_id, Assessed.id)
 
467
    path = Unicode()
 
468
    revision = Int()
 
469
    date_submitted = DateTime()
 
470
 
 
471
 
392
472
# WORKSHEETS AND EXERCISES #
393
473
 
394
474
class Exercise(Storm):
401
481
    include = Unicode()
402
482
    num_rows = Int()
403
483
 
 
484
    worksheet_exercises =  ReferenceSet(id,
 
485
        'WorksheetExercise.exercise_id')
 
486
 
404
487
    worksheets = ReferenceSet(id,
405
488
        'WorksheetExercise.exercise_id',
406
489
        'WorksheetExercise.worksheet_id',
407
490
        'Worksheet.id'
408
491
    )
409
492
    
410
 
    test_suites = ReferenceSet(id, 'TestSuite.exercise_id')
 
493
    test_suites = ReferenceSet(id, 
 
494
        'TestSuite.exercise_id',
 
495
        order_by='seq_no')
411
496
 
412
497
    __init__ = _kwarg_init
413
498
 
416
501
 
417
502
    def get_permissions(self, user):
418
503
        perms = set()
 
504
        roles = set()
419
505
        if user is not None:
420
506
            if user.admin:
421
507
                perms.add('edit')
422
508
                perms.add('view')
 
509
            elif 'lecturer' in set((e.role for e in user.active_enrolments)):
 
510
                perms.add('edit')
 
511
                perms.add('view')
 
512
            
423
513
        return perms
 
514
    
 
515
    def get_description(self):
 
516
        return rst(self.description)
 
517
 
 
518
    def delete(self):
 
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:
 
523
            suite.delete()
 
524
        Store.of(self).remove(self)
424
525
 
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.
 
547
 
446
548
    @property
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()
466
568
 
467
 
    def remove_all_exercises(self, store):
 
569
    def remove_all_exercises(self):
468
570
        """
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.
472
574
        """
 
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()
475
581
            
476
582
    def get_permissions(self, user):
477
583
        return self.offering.get_permissions(user)
478
 
 
 
584
    
 
585
    def get_xml(self):
 
586
        """Returns the xml of this worksheet, converts from rst if required."""
 
587
        if self.format == u'rst':
 
588
            ws_xml = rst(self.data)
 
589
            return ws_xml
 
590
        else:
 
591
            return self.data
 
592
    
 
593
    def delete(self):
 
594
        """Deletes the worksheet, provided it has no attempts on any exercises.
 
595
        
 
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()
 
601
        
 
602
        self.remove_all_exercises()
 
603
        Store.of(self).remove(self)
 
604
        
479
605
class WorksheetExercise(Storm):
480
606
    __storm_table__ = "worksheet_exercise"
481
607
    
498
624
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
499
625
                                  self.worksheet.identifier)
500
626
 
 
627
    def get_permissions(self, user):
 
628
        return self.worksheet.get_permissions(user)
 
629
    
 
630
 
501
631
class ExerciseSave(Storm):
502
632
    """
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')
 
696
    
 
697
    def delete(self):
 
698
        """Delete this suite, without asking questions."""
 
699
        for vaariable in self.variables:
 
700
            variable.delete()
 
701
        for test_case in self.test_cases:
 
702
            test_case.delete()
 
703
        Store.of(self).remove(self)
566
704
 
567
705
class TestCase(Storm):
568
706
    """A TestCase is a member of a TestSuite.
582
720
    parts = ReferenceSet(testid, "TestCasePart.testid")
583
721
    
584
722
    __init__ = _kwarg_init
 
723
    
 
724
    def delete(self):
 
725
        for part in self.parts:
 
726
            part.delete()
 
727
        Store.of(self).remove(self)
585
728
 
586
729
class TestSuiteVar(Storm):
587
730
    """A container for the arguments of a Test Suite"""
599
742
    
600
743
    __init__ = _kwarg_init
601
744
    
 
745
    def delete(self):
 
746
        Store.of(self).remove(self)
 
747
    
602
748
class TestCasePart(Storm):
603
749
    """A container for the test elements of a Test Case"""
604
750
    __storm_table__ = "test_case_part"
615
761
    test = Reference(testid, "TestCase.testid")
616
762
    
617
763
    __init__ = _kwarg_init
 
764
    
 
765
    def delete(self):
 
766
        Store.of(self).remove(self)