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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: Matt Giuca
  • Date: 2009-02-24 02:02:03 UTC
  • mto: This revision was merged to the branch mainline in revision 1119.
  • Revision ID: matt.giuca@gmail.com-20090224020203-aqdcjnsj6y7wl32o
Added a new look to the IVLE header bar. Mmmm... Web 2.0.
Added top-level directory image-source, containing SVG and script files for
    generating the images.
ivle/webapp/coremedia/images: Added 'chrome' directory containing the rendered
    images.
Modified ivle/webapp/base/ivle-headings.html and
    ivle/webapp/coremedia/ivle.css to support the new images.
    Note that the H1 and H2 at the top of the page are no longer displayed
    (and their custom styles have been removed). There is a heading image
    instead.

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
33
32
 
34
33
import ivle.conf
35
 
from ivle.worksheet.rst import rst
 
34
import ivle.caps
36
35
 
37
36
__all__ = ['get_store',
38
37
            'User',
40
39
            'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
41
40
            'Exercise', 'Worksheet', 'WorksheetExercise',
42
41
            'ExerciseSave', 'ExerciseAttempt',
43
 
            'TestCase', 'TestSuite', 'TestSuiteVar'
 
42
            'AlreadyEnrolledError', 'TestCase', 'TestSuite', 'TestSuiteVar'
44
43
        ]
45
44
 
46
45
def _kwarg_init(self, **kwargs):
88
87
    login = Unicode()
89
88
    passhash = Unicode()
90
89
    state = Unicode()
91
 
    admin = Bool()
 
90
    rolenm = Unicode()
92
91
    unixid = Int()
93
92
    nick = Unicode()
94
93
    pass_exp = DateTime()
100
99
    studentid = Unicode()
101
100
    settings = Unicode()
102
101
 
 
102
    def _get_role(self):
 
103
        if self.rolenm is None:
 
104
            return None
 
105
        return ivle.caps.Role(self.rolenm)
 
106
    def _set_role(self, value):
 
107
        if not isinstance(value, ivle.caps.Role):
 
108
            raise TypeError("role must be an ivle.caps.Role")
 
109
        self.rolenm = unicode(value)
 
110
    role = property(_get_role, _set_role)
 
111
 
103
112
    __init__ = _kwarg_init
104
113
 
105
114
    def __repr__(self):
116
125
            return None
117
126
        return self.hash_password(password) == self.passhash
118
127
 
 
128
    def hasCap(self, capability):
 
129
        """Given a capability (which is a Role object), returns True if this
 
130
        User has that capability, False otherwise.
 
131
        """
 
132
        return self.role.hasCap(capability)
 
133
 
119
134
    @property
120
135
    def password_expired(self):
121
136
        fieldval = self.pass_exp
197
212
        return store.find(cls, cls.login == unicode(login)).one()
198
213
 
199
214
    def get_permissions(self, user):
200
 
        if user and user.admin or user is self:
 
215
        if user and user.rolenm == 'admin' or user is self:
201
216
            return set(['view', 'edit'])
202
217
        else:
203
218
            return set()
224
239
        perms = set()
225
240
        if user is not None:
226
241
            perms.add('view')
227
 
            if user.admin:
 
242
            if user.rolenm == 'admin':
228
243
                perms.add('edit')
229
244
        return perms
230
245
 
234
249
    id = Int(primary=True, name="semesterid")
235
250
    year = Unicode()
236
251
    semester = Unicode()
237
 
    state = Unicode()
 
252
    active = Bool()
238
253
 
239
254
    offerings = ReferenceSet(id, 'Offering.semester_id')
240
 
    enrolments = ReferenceSet(id,
241
 
                              'Offering.semester_id',
242
 
                              'Offering.id',
243
 
                              'Enrolment.offering_id')
244
255
 
245
256
    __init__ = _kwarg_init
246
257
 
266
277
 
267
278
    worksheets = ReferenceSet(id, 
268
279
        'Worksheet.offering_id', 
269
 
        order_by="seq_no"
 
280
        order_by="Worksheet.seq_no"
270
281
    )
271
282
 
272
283
    __init__ = _kwarg_init
275
286
        return "<%s %r in %r>" % (type(self).__name__, self.subject,
276
287
                                  self.semester)
277
288
 
278
 
    def enrol(self, user, role=u'student'):
 
289
    def enrol(self, user):
279
290
        '''Enrol a user in this offering.'''
280
 
        enrolment = Store.of(self).find(Enrolment,
281
 
                               Enrolment.user_id == user.id,
282
 
                               Enrolment.offering_id == self.id).one()
283
 
 
284
 
        if enrolment is None:
285
 
            enrolment = Enrolment(user=user, offering=self)
286
 
            self.enrolments.add(enrolment)
287
 
 
288
 
        enrolment.active = True
289
 
        enrolment.role = role
290
 
 
291
 
    def unenrol(self, user):
292
 
        '''Unenrol a user from this offering.'''
293
 
        enrolment = Store.of(self).find(Enrolment,
294
 
                               Enrolment.user_id == user.id,
295
 
                               Enrolment.offering_id == self.id).one()
296
 
        Store.of(enrolment).remove(enrolment)
 
291
        # We'll get a horrible database constraint violation error if we try
 
292
        # to add a second enrolment.
 
293
        if Store.of(self).find(Enrolment,
 
294
                               Enrolment.user_id == user.id,
 
295
                               Enrolment.offering_id == self.id).count() == 1:
 
296
            raise AlreadyEnrolledError()
 
297
 
 
298
        e = Enrolment(user=user, offering=self, active=True)
 
299
        self.enrolments.add(e)
297
300
 
298
301
    def get_permissions(self, user):
299
302
        perms = set()
300
303
        if user is not None:
301
 
            enrolment = self.get_enrolment(user)
302
 
            if enrolment or user.admin:
303
 
                perms.add('view')
304
 
            if (enrolment and enrolment.role in (u'tutor', u'lecturer')) \
305
 
               or user.admin:
 
304
            perms.add('view')
 
305
            if user.rolenm in ('admin', 'lecturer'):
306
306
                perms.add('edit')
307
307
        return perms
308
308
 
309
 
    def get_enrolment(self, user):
310
 
        try:
311
 
            enrolment = self.enrolments.find(user=user).one()
312
 
        except NotOneError:
313
 
            enrolment = None
314
 
 
315
 
        return enrolment
316
 
 
317
309
class Enrolment(Storm):
318
310
    __storm_table__ = "enrolment"
319
311
    __storm_primary__ = "user_id", "offering_id"
322
314
    user = Reference(user_id, User.id)
323
315
    offering_id = Int(name="offeringid")
324
316
    offering = Reference(offering_id, Offering.id)
325
 
    role = Unicode()
326
317
    notes = Unicode()
327
318
    active = Bool()
328
319
 
340
331
        return "<%s %r in %r>" % (type(self).__name__, self.user,
341
332
                                  self.offering)
342
333
 
 
334
class AlreadyEnrolledError(Exception):
 
335
    pass
 
336
 
343
337
# PROJECTS #
344
338
 
345
339
class ProjectSet(Storm):
425
419
    include = Unicode()
426
420
    num_rows = Int()
427
421
 
428
 
    worksheet_exercises =  ReferenceSet(id,
429
 
        'WorksheetExercise.exercise_id')
430
 
 
431
422
    worksheets = ReferenceSet(id,
432
423
        'WorksheetExercise.exercise_id',
433
424
        'WorksheetExercise.worksheet_id',
434
425
        'Worksheet.id'
435
426
    )
436
427
    
437
 
    test_suites = ReferenceSet(id, 
438
 
        'TestSuite.exercise_id',
439
 
        order_by='seq_no')
 
428
    test_suites = ReferenceSet(id, 'TestSuite.exercise_id')
440
429
 
441
430
    __init__ = _kwarg_init
442
431
 
445
434
 
446
435
    def get_permissions(self, user):
447
436
        perms = set()
448
 
        roles = set()
449
437
        if user is not None:
450
 
            if user.admin:
451
 
                perms.add('edit')
452
 
                perms.add('view')
453
 
            elif 'lecturer' in set((e.role for e in user.active_enrolments)):
454
 
                perms.add('edit')
455
 
                perms.add('view')
456
 
            
 
438
            if user.rolenm in ('admin', 'lecturer'):
 
439
                perms.add('edit')
 
440
                perms.add('view')
457
441
        return perms
458
 
    
459
 
    def get_description(self):
460
 
        return rst(self.description)
461
 
 
462
 
    def delete(self):
463
 
        """Deletes the exercise, providing it has no associated worksheets."""
464
 
        if (self.worksheet_exercises.count() > 0):
465
 
            raise IntegrityError()
466
 
        for suite in self.test_suites:
467
 
            suite.delete()
468
 
        Store.of(self).remove(self)
469
442
 
470
443
class Worksheet(Storm):
471
444
    __storm_table__ = "worksheet"
482
455
    attempts = ReferenceSet(id, "ExerciseAttempt.worksheetid")
483
456
    offering = Reference(offering_id, 'Offering.id')
484
457
 
485
 
    all_worksheet_exercises = ReferenceSet(id,
 
458
    # Use worksheet_exercises to get access to the WorksheetExercise objects
 
459
    # binding worksheets to exercises. This is required to access the
 
460
    # "optional" field.
 
461
    worksheet_exercises = ReferenceSet(id,
486
462
        'WorksheetExercise.worksheet_id')
487
 
 
488
 
    # Use worksheet_exercises to get access to the *active* WorksheetExercise
489
 
    # objects binding worksheets to exercises. This is required to access the
490
 
    # "optional" field.
491
 
 
492
 
    @property
493
 
    def worksheet_exercises(self):
494
 
        return self.all_worksheet_exercises.find(active=True)
 
463
        
495
464
 
496
465
    __init__ = _kwarg_init
497
466
 
510
479
        return store.find(cls, cls.subject == unicode(subjectname),
511
480
            cls.name == unicode(worksheetname)).one()
512
481
 
513
 
    def remove_all_exercises(self):
 
482
    def remove_all_exercises(self, store):
514
483
        """
515
484
        Remove all exercises from this worksheet.
516
485
        This does not delete the exercises themselves. It just removes them
517
486
        from the worksheet.
518
487
        """
519
 
        store = Store.of(self)
520
 
        for ws_ex in self.all_worksheet_exercises:
521
 
            if ws_ex.saves.count() > 0 or ws_ex.attempts.count() > 0:
522
 
                raise IntegrityError()
523
488
        store.find(WorksheetExercise,
524
489
            WorksheetExercise.worksheet == self).remove()
525
490
            
526
491
    def get_permissions(self, user):
527
492
        return self.offering.get_permissions(user)
528
 
    
529
 
    def get_xml(self):
530
 
        """Returns the xml of this worksheet, converts from rst if required."""
531
 
        if self.format == u'rst':
532
 
            ws_xml = rst(self.data)
533
 
            return ws_xml
534
 
        else:
535
 
            return self.data
536
 
    
537
 
    def delete(self):
538
 
        """Deletes the worksheet, provided it has no attempts on any exercises.
539
 
        
540
 
        Returns True if delete succeeded, or False if this worksheet has
541
 
        attempts attached."""
542
 
        for ws_ex in self.all_worksheet_exercises:
543
 
            if ws_ex.saves.count() > 0 or ws_ex.attempts.count() > 0:
544
 
                raise IntegrityError()
545
 
        
546
 
        self.remove_all_exercises()
547
 
        Store.of(self).remove(self)
548
 
        
 
493
 
549
494
class WorksheetExercise(Storm):
550
495
    __storm_table__ = "worksheet_exercise"
551
496
    
568
513
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
569
514
                                  self.worksheet.identifier)
570
515
 
571
 
    def get_permissions(self, user):
572
 
        return self.worksheet.get_permissions(user)
573
 
    
574
 
 
575
516
class ExerciseSave(Storm):
576
517
    """
577
518
    Represents a potential solution to an exercise that a user has submitted
635
576
    function = Unicode()
636
577
    stdin = Unicode()
637
578
    exercise = Reference(exercise_id, Exercise.id)
638
 
    test_cases = ReferenceSet(suiteid, 'TestCase.suiteid', order_by="seq_no")
639
 
    variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid', order_by='arg_no')
640
 
    
641
 
    def delete(self):
642
 
        """Delete this suite, without asking questions."""
643
 
        for vaariable in self.variables:
644
 
            variable.delete()
645
 
        for test_case in self.test_cases:
646
 
            test_case.delete()
647
 
        Store.of(self).remove(self)
 
579
    test_cases = ReferenceSet(suiteid, 'TestCase.suiteid')
 
580
    variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid')
648
581
 
649
582
class TestCase(Storm):
650
583
    """A TestCase is a member of a TestSuite.
664
597
    parts = ReferenceSet(testid, "TestCasePart.testid")
665
598
    
666
599
    __init__ = _kwarg_init
667
 
    
668
 
    def delete(self):
669
 
        for part in self.parts:
670
 
            part.delete()
671
 
        Store.of(self).remove(self)
672
600
 
673
601
class TestSuiteVar(Storm):
674
602
    """A container for the arguments of a Test Suite"""
686
614
    
687
615
    __init__ = _kwarg_init
688
616
    
689
 
    def delete(self):
690
 
        Store.of(self).remove(self)
691
 
    
692
617
class TestCasePart(Storm):
693
618
    """A container for the test elements of a Test Case"""
694
619
    __storm_table__ = "test_case_part"
705
630
    test = Reference(testid, "TestCase.testid")
706
631
    
707
632
    __init__ = _kwarg_init
708
 
    
709
 
    def delete(self):
710
 
        Store.of(self).remove(self)