Initial checkin of new API implementation
[plcapi.git] / PLC / Table.py
1 class Row(dict):
2     """
3     Representation of a row in a database table. To use, optionally
4     instantiate with a dict of values. Update as you would a
5     dict. Commit to the database with flush().
6     """
7
8     # Set this to a dict of the valid columns in this table. If a column
9     # name ends in 's' and the column value is set by referring to the
10     # column without the 's', it is assumed that the column values
11     # should be aggregated into lists. For example, if fields contains
12     # the column 'role_ids' and row['role_id'] is set repeatedly to
13     # different values, row['role_ids'] will contain a list of the set
14     # values.
15     fields = {}
16
17     # These fields are derived from join tables and are not actually
18     # in the sites table.
19     join_fields = {}
20
21     # These fields are derived from join tables and are not returned
22     # by default unless specified.
23     extra_fields = {}
24
25     def __init__(self, fields):
26         self.update(fields)
27         
28     def update(self, fields):
29         for key, value in fields.iteritems():
30             self.__setitem__(key, value)
31
32     def __setitem__(self, key, value):
33         """
34         Magically takes care of aggregating certain variables into
35         lists.
36         """
37
38         # All known keys
39         all_fields = self.fields.keys() + \
40                      self.join_fields.keys() + \
41                      self.extra_fields.keys()
42
43         # Aggregate into lists
44         if (key + 's') in all_fields:
45             key += 's'
46             try:
47                 if value not in self[key] and value is not None:
48                     self[key].append(value)
49             except KeyError:
50                 if value is None:
51                     self[key] = []
52                 else:
53                     self[key] = [value]
54             return
55
56         elif key in all_fields:
57             dict.__setitem__(self, key, value)
58
59     def validate(self):
60         """
61         Validates values. Will validate a value with a custom function
62         if a function named 'validate_[key]' exists.
63         """
64
65         # Validate values before committing
66         # XXX Also truncate strings that are too long
67         for key, value in self.iteritems():
68             if value is not None and hasattr(self, 'validate_' + key):
69                 validate = getattr(self, 'validate_' + key)
70                 self[key] = validate(value)
71
72     def flush(self, commit = True):
73         """
74         Flush changes back to the database.
75         """
76
77         pass
78
79 class Table(dict):
80     """
81     Representation of row(s) in a database table.
82     """
83
84     def flush(self, commit = True):
85         """
86         Flush changes back to the database.
87         """
88
89         for row in self.values():
90             row.flush(commit)