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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: Nick Chadwick
  • Date: 2009-03-03 01:48:48 UTC
  • mto: (1099.1.227 exercise-ui)
  • mto: This revision was merged to the branch mainline in revision 1162.
  • Revision ID: chadnickbok@gmail.com-20090303014848-dyurvmtmbneohd7f
Modified the setup script to include '.txt' files.

This allows the automatic inclusion of definitions.txt from the rst
code, as it is needed by all worksheets.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
# Author: Matt Giuca, Will Grant
 
19
 
 
20
"""
 
21
Database Classes and Utilities for Storm ORM
 
22
 
 
23
This module provides all of the classes which map to database tables.
 
24
It also provides miscellaneous utility functions for database interaction.
 
25
"""
 
26
 
 
27
import md5
 
28
import datetime
 
29
 
 
30
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
 
31
                         Reference, ReferenceSet, Bool, Storm, Desc
 
32
from storm.exceptions import NotOneError
 
33
 
 
34
import ivle.conf
 
35
from ivle.worksheet.rst import rst
 
36
 
 
37
__all__ = ['get_store',
 
38
            'User',
 
39
            'Subject', 'Semester', 'Offering', 'Enrolment',
 
40
            'ProjectSet', 'Project', 'ProjectGroup', 'ProjectGroupMembership',
 
41
            'Exercise', 'Worksheet', 'WorksheetExercise',
 
42
            'ExerciseSave', 'ExerciseAttempt',
 
43
            'TestCase', 'TestSuite', 'TestSuiteVar'
 
44
        ]
 
45
 
 
46
def _kwarg_init(self, **kwargs):
 
47
    for k,v in kwargs.items():
 
48
        if k.startswith('_') or not hasattr(self.__class__, k):
 
49
            raise TypeError("%s got an unexpected keyword argument '%s'"
 
50
                % (self.__class__.__name__, k))
 
51
        setattr(self, k, v)
 
52
 
 
53
def get_conn_string():
 
54
    """
 
55
    Returns the Storm connection string, generated from the conf file.
 
56
    """
 
57
 
 
58
    clusterstr = ''
 
59
    if ivle.conf.db_user:
 
60
        clusterstr += ivle.conf.db_user
 
61
        if ivle.conf.db_password:
 
62
            clusterstr += ':' + ivle.conf.db_password
 
63
        clusterstr += '@'
 
64
 
 
65
    host = ivle.conf.db_host or 'localhost'
 
66
    port = ivle.conf.db_port or 5432
 
67
 
 
68
    clusterstr += '%s:%d' % (host, port)
 
69
 
 
70
    return "postgres://%s/%s" % (clusterstr, ivle.conf.db_dbname)
 
71
 
 
72
def get_store():
 
73
    """
 
74
    Open a database connection and transaction. Return a storm.store.Store
 
75
    instance connected to the configured IVLE database.
 
76
    """
 
77
    return Store(create_database(get_conn_string()))
 
78
 
 
79
# USERS #
 
80
 
 
81
class User(Storm):
 
82
    """
 
83
    Represents an IVLE user.
 
84
    """
 
85
    __storm_table__ = "login"
 
86
 
 
87
    id = Int(primary=True, name="loginid")
 
88
    login = Unicode()
 
89
    passhash = Unicode()
 
90
    state = Unicode()
 
91
    admin = Bool()
 
92
    unixid = Int()
 
93
    nick = Unicode()
 
94
    pass_exp = DateTime()
 
95
    acct_exp = DateTime()
 
96
    last_login = DateTime()
 
97
    svn_pass = Unicode()
 
98
    email = Unicode()
 
99
    fullname = Unicode()
 
100
    studentid = Unicode()
 
101
    settings = Unicode()
 
102
 
 
103
    __init__ = _kwarg_init
 
104
 
 
105
    def __repr__(self):
 
106
        return "<%s '%s'>" % (type(self).__name__, self.login)
 
107
 
 
108
    def authenticate(self, password):
 
109
        """Validate a given password against this user.
 
110
 
 
111
        Returns True if the given password matches the password hash for this
 
112
        User, False if it doesn't match, and None if there is no hash for the
 
113
        user.
 
114
        """
 
115
        if self.passhash is None:
 
116
            return None
 
117
        return self.hash_password(password) == self.passhash
 
118
 
 
119
    @property
 
120
    def password_expired(self):
 
121
        fieldval = self.pass_exp
 
122
        return fieldval is not None and datetime.datetime.now() > fieldval
 
123
 
 
124
    @property
 
125
    def account_expired(self):
 
126
        fieldval = self.acct_exp
 
127
        return fieldval is not None and datetime.datetime.now() > fieldval
 
128
 
 
129
    @property
 
130
    def valid(self):
 
131
        return self.state == 'enabled' and not self.account_expired
 
132
 
 
133
    def _get_enrolments(self, justactive):
 
134
        return Store.of(self).find(Enrolment,
 
135
            Enrolment.user_id == self.id,
 
136
            (Enrolment.active == True) if justactive else True,
 
137
            Enrolment.offering_id == Offering.id,
 
138
            Offering.semester_id == Semester.id,
 
139
            Offering.subject_id == Subject.id).order_by(
 
140
                Desc(Semester.year),
 
141
                Desc(Semester.semester),
 
142
                Desc(Subject.code)
 
143
            )
 
144
 
 
145
    def _set_password(self, password):
 
146
        if password is None:
 
147
            self.passhash = None
 
148
        else:
 
149
            self.passhash = unicode(User.hash_password(password))
 
150
    password = property(fset=_set_password)
 
151
 
 
152
    @property
 
153
    def subjects(self):
 
154
        return Store.of(self).find(Subject,
 
155
            Enrolment.user_id == self.id,
 
156
            Enrolment.active == True,
 
157
            Offering.id == Enrolment.offering_id,
 
158
            Subject.id == Offering.subject_id).config(distinct=True)
 
159
 
 
160
    # TODO: Invitations should be listed too?
 
161
    def get_groups(self, offering=None):
 
162
        preds = [
 
163
            ProjectGroupMembership.user_id == self.id,
 
164
            ProjectGroup.id == ProjectGroupMembership.project_group_id,
 
165
        ]
 
166
        if offering:
 
167
            preds.extend([
 
168
                ProjectSet.offering_id == offering.id,
 
169
                ProjectGroup.project_set_id == ProjectSet.id,
 
170
            ])
 
171
        return Store.of(self).find(ProjectGroup, *preds)
 
172
 
 
173
    @property
 
174
    def groups(self):
 
175
        return self.get_groups()
 
176
 
 
177
    @property
 
178
    def active_enrolments(self):
 
179
        '''A sanely ordered list of the user's active enrolments.'''
 
180
        return self._get_enrolments(True)
 
181
 
 
182
    @property
 
183
    def enrolments(self):
 
184
        '''A sanely ordered list of all of the user's enrolments.'''
 
185
        return self._get_enrolments(False) 
 
186
 
 
187
    @staticmethod
 
188
    def hash_password(password):
 
189
        return md5.md5(password).hexdigest()
 
190
 
 
191
    @classmethod
 
192
    def get_by_login(cls, store, login):
 
193
        """
 
194
        Get the User from the db associated with a given store and
 
195
        login.
 
196
        """
 
197
        return store.find(cls, cls.login == unicode(login)).one()
 
198
 
 
199
    def get_permissions(self, user):
 
200
        if user and user.admin or user is self:
 
201
            return set(['view', 'edit'])
 
202
        else:
 
203
            return set()
 
204
 
 
205
# SUBJECTS AND ENROLMENTS #
 
206
 
 
207
class Subject(Storm):
 
208
    __storm_table__ = "subject"
 
209
 
 
210
    id = Int(primary=True, name="subjectid")
 
211
    code = Unicode(name="subj_code")
 
212
    name = Unicode(name="subj_name")
 
213
    short_name = Unicode(name="subj_short_name")
 
214
    url = Unicode()
 
215
 
 
216
    offerings = ReferenceSet(id, 'Offering.subject_id')
 
217
 
 
218
    __init__ = _kwarg_init
 
219
 
 
220
    def __repr__(self):
 
221
        return "<%s '%s'>" % (type(self).__name__, self.short_name)
 
222
 
 
223
    def get_permissions(self, user):
 
224
        perms = set()
 
225
        if user is not None:
 
226
            perms.add('view')
 
227
            if user.admin:
 
228
                perms.add('edit')
 
229
        return perms
 
230
 
 
231
class Semester(Storm):
 
232
    __storm_table__ = "semester"
 
233
 
 
234
    id = Int(primary=True, name="semesterid")
 
235
    year = Unicode()
 
236
    semester = Unicode()
 
237
    state = Unicode()
 
238
 
 
239
    offerings = ReferenceSet(id, 'Offering.semester_id')
 
240
    enrolments = ReferenceSet(id,
 
241
                              'Offering.semester_id',
 
242
                              'Offering.id',
 
243
                              'Enrolment.offering_id')
 
244
 
 
245
    __init__ = _kwarg_init
 
246
 
 
247
    def __repr__(self):
 
248
        return "<%s %s/%s>" % (type(self).__name__, self.year, self.semester)
 
249
 
 
250
class Offering(Storm):
 
251
    __storm_table__ = "offering"
 
252
 
 
253
    id = Int(primary=True, name="offeringid")
 
254
    subject_id = Int(name="subject")
 
255
    subject = Reference(subject_id, Subject.id)
 
256
    semester_id = Int(name="semesterid")
 
257
    semester = Reference(semester_id, Semester.id)
 
258
    groups_student_permissions = Unicode()
 
259
 
 
260
    enrolments = ReferenceSet(id, 'Enrolment.offering_id')
 
261
    members = ReferenceSet(id,
 
262
                           'Enrolment.offering_id',
 
263
                           'Enrolment.user_id',
 
264
                           'User.id')
 
265
    project_sets = ReferenceSet(id, 'ProjectSet.offering_id')
 
266
 
 
267
    worksheets = ReferenceSet(id, 
 
268
        'Worksheet.offering_id', 
 
269
        order_by="seq_no"
 
270
    )
 
271
 
 
272
    __init__ = _kwarg_init
 
273
 
 
274
    def __repr__(self):
 
275
        return "<%s %r in %r>" % (type(self).__name__, self.subject,
 
276
                                  self.semester)
 
277
 
 
278
    def enrol(self, user, role=u'student'):
 
279
        '''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 get_permissions(self, user):
 
292
        perms = set()
 
293
        if user is not None:
 
294
            perms.add('view')
 
295
            if user.admin:
 
296
                perms.add('edit')
 
297
        return perms
 
298
 
 
299
    def get_enrolment(self, user):
 
300
        try:
 
301
            enrolment = self.enrolments.find(user=user).one()
 
302
        except NotOneError:
 
303
            enrolment = None
 
304
 
 
305
        return enrolment
 
306
 
 
307
class Enrolment(Storm):
 
308
    __storm_table__ = "enrolment"
 
309
    __storm_primary__ = "user_id", "offering_id"
 
310
 
 
311
    user_id = Int(name="loginid")
 
312
    user = Reference(user_id, User.id)
 
313
    offering_id = Int(name="offeringid")
 
314
    offering = Reference(offering_id, Offering.id)
 
315
    role = Unicode()
 
316
    notes = Unicode()
 
317
    active = Bool()
 
318
 
 
319
    @property
 
320
    def groups(self):
 
321
        return Store.of(self).find(ProjectGroup,
 
322
                ProjectSet.offering_id == self.offering.id,
 
323
                ProjectGroup.project_set_id == ProjectSet.id,
 
324
                ProjectGroupMembership.project_group_id == ProjectGroup.id,
 
325
                ProjectGroupMembership.user_id == self.user.id)
 
326
 
 
327
    __init__ = _kwarg_init
 
328
 
 
329
    def __repr__(self):
 
330
        return "<%s %r in %r>" % (type(self).__name__, self.user,
 
331
                                  self.offering)
 
332
 
 
333
# PROJECTS #
 
334
 
 
335
class ProjectSet(Storm):
 
336
    __storm_table__ = "project_set"
 
337
 
 
338
    id = Int(name="projectsetid", primary=True)
 
339
    offering_id = Int(name="offeringid")
 
340
    offering = Reference(offering_id, Offering.id)
 
341
    max_students_per_group = Int()
 
342
 
 
343
    projects = ReferenceSet(id, 'Project.project_set_id')
 
344
    project_groups = ReferenceSet(id, 'ProjectGroup.project_set_id')
 
345
 
 
346
    __init__ = _kwarg_init
 
347
 
 
348
    def __repr__(self):
 
349
        return "<%s %d in %r>" % (type(self).__name__, self.id,
 
350
                                  self.offering)
 
351
 
 
352
class Project(Storm):
 
353
    __storm_table__ = "project"
 
354
 
 
355
    id = Int(name="projectid", primary=True)
 
356
    synopsis = Unicode()
 
357
    url = Unicode()
 
358
    project_set_id = Int(name="projectsetid")
 
359
    project_set = Reference(project_set_id, ProjectSet.id)
 
360
    deadline = DateTime()
 
361
 
 
362
    __init__ = _kwarg_init
 
363
 
 
364
    def __repr__(self):
 
365
        return "<%s '%s' in %r>" % (type(self).__name__, self.synopsis,
 
366
                                  self.project_set.offering)
 
367
 
 
368
class ProjectGroup(Storm):
 
369
    __storm_table__ = "project_group"
 
370
 
 
371
    id = Int(name="groupid", primary=True)
 
372
    name = Unicode(name="groupnm")
 
373
    project_set_id = Int(name="projectsetid")
 
374
    project_set = Reference(project_set_id, ProjectSet.id)
 
375
    nick = Unicode()
 
376
    created_by_id = Int(name="createdby")
 
377
    created_by = Reference(created_by_id, User.id)
 
378
    epoch = DateTime()
 
379
 
 
380
    members = ReferenceSet(id,
 
381
                           "ProjectGroupMembership.project_group_id",
 
382
                           "ProjectGroupMembership.user_id",
 
383
                           "User.id")
 
384
 
 
385
    __init__ = _kwarg_init
 
386
 
 
387
    def __repr__(self):
 
388
        return "<%s %s in %r>" % (type(self).__name__, self.name,
 
389
                                  self.project_set.offering)
 
390
 
 
391
class ProjectGroupMembership(Storm):
 
392
    __storm_table__ = "group_member"
 
393
    __storm_primary__ = "user_id", "project_group_id"
 
394
 
 
395
    user_id = Int(name="loginid")
 
396
    user = Reference(user_id, User.id)
 
397
    project_group_id = Int(name="groupid")
 
398
    project_group = Reference(project_group_id, ProjectGroup.id)
 
399
 
 
400
    __init__ = _kwarg_init
 
401
 
 
402
    def __repr__(self):
 
403
        return "<%s %r in %r>" % (type(self).__name__, self.user,
 
404
                                  self.project_group)
 
405
 
 
406
# WORKSHEETS AND EXERCISES #
 
407
 
 
408
class Exercise(Storm):
 
409
    __storm_table__ = "exercise"
 
410
    id = Unicode(primary=True, name="identifier")
 
411
    name = Unicode()
 
412
    description = Unicode()
 
413
    partial = Unicode()
 
414
    solution = Unicode()
 
415
    include = Unicode()
 
416
    num_rows = Int()
 
417
 
 
418
    worksheets = ReferenceSet(id,
 
419
        'WorksheetExercise.exercise_id',
 
420
        'WorksheetExercise.worksheet_id',
 
421
        'Worksheet.id'
 
422
    )
 
423
    
 
424
    test_suites = ReferenceSet(id, 
 
425
        'TestSuite.exercise_id',
 
426
        order_by='seq_no')
 
427
 
 
428
    __init__ = _kwarg_init
 
429
 
 
430
    def __repr__(self):
 
431
        return "<%s %s>" % (type(self).__name__, self.name)
 
432
 
 
433
    def get_permissions(self, user):
 
434
        perms = set()
 
435
        if user is not None:
 
436
            if user.admin:
 
437
                perms.add('edit')
 
438
                perms.add('view')
 
439
        return perms
 
440
 
 
441
class Worksheet(Storm):
 
442
    __storm_table__ = "worksheet"
 
443
 
 
444
    id = Int(primary=True, name="worksheetid")
 
445
    offering_id = Int(name="offeringid")
 
446
    identifier = Unicode()
 
447
    name = Unicode()
 
448
    assessable = Bool()
 
449
    data = Unicode()
 
450
    seq_no = Int()
 
451
    format = Unicode()
 
452
 
 
453
    attempts = ReferenceSet(id, "ExerciseAttempt.worksheetid")
 
454
    offering = Reference(offering_id, 'Offering.id')
 
455
 
 
456
    all_worksheet_exercises = ReferenceSet(id,
 
457
        'WorksheetExercise.worksheet_id')
 
458
 
 
459
    # Use worksheet_exercises to get access to the *active* WorksheetExercise
 
460
    # objects binding worksheets to exercises. This is required to access the
 
461
    # "optional" field.
 
462
 
 
463
    @property
 
464
    def worksheet_exercises(self):
 
465
        return self.all_worksheet_exercises.find(active=True)
 
466
 
 
467
    __init__ = _kwarg_init
 
468
 
 
469
    def __repr__(self):
 
470
        return "<%s %s>" % (type(self).__name__, self.name)
 
471
 
 
472
    # XXX Refactor this - make it an instance method of Subject rather than a
 
473
    # class method of Worksheet. Can't do that now because Subject isn't
 
474
    # linked referentially to the Worksheet.
 
475
    @classmethod
 
476
    def get_by_name(cls, store, subjectname, worksheetname):
 
477
        """
 
478
        Get the Worksheet from the db associated with a given store, subject
 
479
        name and worksheet name.
 
480
        """
 
481
        return store.find(cls, cls.subject == unicode(subjectname),
 
482
            cls.name == unicode(worksheetname)).one()
 
483
 
 
484
    def remove_all_exercises(self, store):
 
485
        """
 
486
        Remove all exercises from this worksheet.
 
487
        This does not delete the exercises themselves. It just removes them
 
488
        from the worksheet.
 
489
        """
 
490
        store.find(WorksheetExercise,
 
491
            WorksheetExercise.worksheet == self).remove()
 
492
            
 
493
    def get_permissions(self, user):
 
494
        return self.offering.get_permissions(user)
 
495
    
 
496
    def get_xml(self):
 
497
        """Returns the xml of this worksheet, converts from rst if required."""
 
498
        if self.format == u'rst':
 
499
            ws_xml = '<worksheet>' + rst(self.data) + '</worksheet>'
 
500
            return ws_xml
 
501
        else:
 
502
            return self.data
 
503
 
 
504
class WorksheetExercise(Storm):
 
505
    __storm_table__ = "worksheet_exercise"
 
506
    
 
507
    id = Int(primary=True, name="ws_ex_id")
 
508
 
 
509
    worksheet_id = Int(name="worksheetid")
 
510
    worksheet = Reference(worksheet_id, Worksheet.id)
 
511
    exercise_id = Unicode(name="exerciseid")
 
512
    exercise = Reference(exercise_id, Exercise.id)
 
513
    optional = Bool()
 
514
    active = Bool()
 
515
    seq_no = Int()
 
516
    
 
517
    saves = ReferenceSet(id, "ExerciseSave.ws_ex_id")
 
518
    attempts = ReferenceSet(id, "ExerciseAttempt.ws_ex_id")
 
519
 
 
520
    __init__ = _kwarg_init
 
521
 
 
522
    def __repr__(self):
 
523
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
 
524
                                  self.worksheet.identifier)
 
525
 
 
526
class ExerciseSave(Storm):
 
527
    """
 
528
    Represents a potential solution to an exercise that a user has submitted
 
529
    to the server for storage.
 
530
    A basic ExerciseSave is just the current saved text for this exercise for
 
531
    this user (doesn't count towards their attempts).
 
532
    ExerciseSave may be extended with additional semantics (such as
 
533
    ExerciseAttempt).
 
534
    """
 
535
    __storm_table__ = "exercise_save"
 
536
    __storm_primary__ = "ws_ex_id", "user_id"
 
537
 
 
538
    ws_ex_id = Int(name="ws_ex_id")
 
539
    worksheet_exercise = Reference(ws_ex_id, "WorksheetExercise.id")
 
540
 
 
541
    user_id = Int(name="loginid")
 
542
    user = Reference(user_id, User.id)
 
543
    date = DateTime()
 
544
    text = Unicode()
 
545
 
 
546
    __init__ = _kwarg_init
 
547
 
 
548
    def __repr__(self):
 
549
        return "<%s %s by %s at %s>" % (type(self).__name__,
 
550
            self.exercise.name, self.user.login, self.date.strftime("%c"))
 
551
 
 
552
class ExerciseAttempt(ExerciseSave):
 
553
    """
 
554
    An ExerciseAttempt is a special case of an ExerciseSave. Like an
 
555
    ExerciseSave, it constitutes exercise solution data that the user has
 
556
    submitted to the server for storage.
 
557
    In addition, it contains additional information about the submission.
 
558
    complete - True if this submission was successful, rendering this exercise
 
559
        complete for this user.
 
560
    active - True if this submission is "active" (usually true). Submissions
 
561
        may be de-activated by privileged users for special reasons, and then
 
562
        they won't count (either as a penalty or success), but will still be
 
563
        stored.
 
564
    """
 
565
    __storm_table__ = "exercise_attempt"
 
566
    __storm_primary__ = "ws_ex_id", "user_id", "date"
 
567
 
 
568
    # The "text" field is the same but has a different name in the DB table
 
569
    # for some reason.
 
570
    text = Unicode(name="attempt")
 
571
    complete = Bool()
 
572
    active = Bool()
 
573
    
 
574
    def get_permissions(self, user):
 
575
        return set(['view']) if user is self.user else set()
 
576
  
 
577
class TestSuite(Storm):
 
578
    """A Testsuite acts as a container for the test cases of an exercise."""
 
579
    __storm_table__ = "test_suite"
 
580
    __storm_primary__ = "exercise_id", "suiteid"
 
581
    
 
582
    suiteid = Int()
 
583
    exercise_id = Unicode(name="exerciseid")
 
584
    description = Unicode()
 
585
    seq_no = Int()
 
586
    function = Unicode()
 
587
    stdin = Unicode()
 
588
    exercise = Reference(exercise_id, Exercise.id)
 
589
    test_cases = ReferenceSet(suiteid, 'TestCase.suiteid', order_by="seq_no")
 
590
    variables = ReferenceSet(suiteid, 'TestSuiteVar.suiteid', order_by='arg_no')
 
591
 
 
592
class TestCase(Storm):
 
593
    """A TestCase is a member of a TestSuite.
 
594
    
 
595
    It contains the data necessary to check if an exercise is correct"""
 
596
    __storm_table__ = "test_case"
 
597
    __storm_primary__ = "testid", "suiteid"
 
598
    
 
599
    testid = Int()
 
600
    suiteid = Int()
 
601
    suite = Reference(suiteid, "TestSuite.suiteid")
 
602
    passmsg = Unicode()
 
603
    failmsg = Unicode()
 
604
    test_default = Unicode()
 
605
    seq_no = Int()
 
606
    
 
607
    parts = ReferenceSet(testid, "TestCasePart.testid")
 
608
    
 
609
    __init__ = _kwarg_init
 
610
 
 
611
class TestSuiteVar(Storm):
 
612
    """A container for the arguments of a Test Suite"""
 
613
    __storm_table__ = "suite_variable"
 
614
    __storm_primary__ = "varid"
 
615
    
 
616
    varid = Int()
 
617
    suiteid = Int()
 
618
    var_name = Unicode()
 
619
    var_value = Unicode()
 
620
    var_type = Unicode()
 
621
    arg_no = Int()
 
622
    
 
623
    suite = Reference(suiteid, "TestSuite.suiteid")
 
624
    
 
625
    __init__ = _kwarg_init
 
626
    
 
627
class TestCasePart(Storm):
 
628
    """A container for the test elements of a Test Case"""
 
629
    __storm_table__ = "test_case_part"
 
630
    __storm_primary__ = "partid"
 
631
    
 
632
    partid = Int()
 
633
    testid = Int()
 
634
    
 
635
    part_type = Unicode()
 
636
    test_type = Unicode()
 
637
    data = Unicode()
 
638
    filename = Unicode()
 
639
    
 
640
    test = Reference(testid, "TestCase.testid")
 
641
    
 
642
    __init__ = _kwarg_init