304c630304635b17da29480bc91bef1c59f2e986
[cascardo/ipsilon.git] / ipsilon / util / config.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Ipsilon project Contributors, for licensee see COPYING
4
5 from ipsilon.util.log import Log
6
7
8 class Config(Log):
9
10     def __init__(self, name, *args):
11         self.name = name
12         self._list = list()
13         self._dict = dict()
14         for item in args:
15             if not isinstance(item, Option):
16                 raise ValueError('Invalid option type for %s' % repr(item))
17             self._list.append(item.name)
18             self._dict[item.name] = item
19         self.debug('Config(%s) %s' % (self.name, self._dict))
20
21     def __repr__(self):
22         return '%s: %s' % (self.__class__, ', '.join(self._list))
23
24     def __str__(self):
25         return str(self._list)
26
27     def __len__(self):
28         return len(self._list)
29
30     def __getitem__(self, key):
31         return self._dict[key]
32
33     def __setitem__(self, key, value):
34         if not isinstance(value, Option):
35             raise ValueError('Invalid type for %s' % value)
36         if key != value.name:
37             raise NameError('Name mismatch, key=%s but value.name=%s' % (
38                 key, value.name))
39         if key not in self._list:
40             self._list.append(key)
41         self._dict[key] = value
42
43     def __delitem__(self, key):
44         self._list.remove(key)
45         del self._dict[key]
46
47     def __iter__(self):
48         i = 0
49         while i < len(self._list):
50             yield self._list[i]
51             i += 1
52
53     def __reversed__(self):
54         i = len(self._list)
55         while i > 0:
56             yield self._list[i - 1]
57             i -= 1
58
59     def __contains__(self, item):
60         return (item in self._dict)
61
62     def iteritems(self):
63         i = 0
64         while i < len(self._list):
65             yield (self._list[i], self._dict[self._list[i]])
66             i += 1
67
68     def items(self):
69         return [(k, self._dict[k]) for k in self._list]
70
71
72 class Option(Log):
73
74     def __init__(self, name, description):
75         self.name = name
76         self.description = description
77         self._default_value = None
78         self._assigned_value = None
79
80     def __repr__(self):
81         return "%s: %s {%s}, value = %s [def: %s]" % (self.__class__,
82                                                       self.name,
83                                                       self.description,
84                                                       self._assigned_value,
85                                                       self._default_value)
86
87     def __str__(self):
88         return '%s=%s' % (self.name, self.get_value())
89
90     def get_value(self, default=True):
91         if self._assigned_value is not None:
92             return self._assigned_value
93         elif default is True:
94             return self._default_value
95         else:
96             return None
97
98     def set_value(self, value):
99         self._assigned_value = value
100
101     def export_value(self):
102         raise NotImplementedError
103
104     def import_value(self, value):
105         raise NotImplementedError
106
107     def _str_export_value(self):
108         if self._assigned_value:
109             return str(self._assigned_value)
110         return None
111
112     def _str_import_value(self, value):
113         if type(value) is not str:
114             raise ValueError('Value must be string')
115         self._assigned_value = value
116
117
118 class String(Option):
119
120     def __init__(self, name, description, default_value=None):
121         super(String, self).__init__(name, description)
122         self._default_value = str(default_value)
123
124     def set_value(self, value):
125         self._assigned_value = str(value)
126
127     def export_value(self):
128         return self._str_export_value()
129
130     def import_value(self, value):
131         self._str_import_value(value)
132
133
134 class Template(Option):
135
136     def __init__(self, name, description, default_template=None):
137         super(Template, self).__init__(name, description)
138         self._default_value = str(default_template)
139
140     def set_value(self, value):
141         self._assigned_value = str(value)
142
143     def templatize(self, args):
144         if not args:
145             raise ValueError('Templatized called w/o arguments')
146
147         return self.get_value() % args
148
149     def export_value(self):
150         return self._str_export_value()
151
152     def import_value(self, value):
153         self._str_import_value(value)
154
155
156 class List(Option):
157
158     def __init__(self, name, description, default_list=None):
159         super(List, self).__init__(name, description)
160         if default_list:
161             self._default_value = list(default_list)
162
163     def set_value(self, value):
164         self._assigned_value = list(value)
165
166     def export_value(self):
167         if self._assigned_value:
168             return ', '.join(self._assigned_value)
169         return None
170
171     def import_value(self, value):
172         if type(value) is not str:
173             raise ValueError('Value (type: %s) must be string' % type(value))
174         self._assigned_value = [x.strip() for x in value.split(',')]
175
176
177 class Choice(Option):
178
179     def __init__(self, name, description, allowed=None, default=None):
180         super(Choice, self).__init__(name, description)
181         if allowed:
182             self._allowed_values = list(allowed)
183         else:
184             self._allowed_values = list()
185         self._default_value = list()
186         if default is None:
187             default = []
188         for name in default:
189             if name not in self._allowed_values:
190                 raise ValueError(
191                     'item [%s] is not in allowed [%s]' % (name, allowed))
192             self._default_value.append(name)
193
194     def __repr__(self):
195         return "%s: %s {%s}, values = %s d:%s ok:%s" % (self.__class__,
196                                                         self.name,
197                                                         self.description,
198                                                         self._assigned_value,
199                                                         self._default_value,
200                                                         self._allowed_values)
201
202     def __str__(self):
203         return '%s=%s' % (self.name, self.get_value())
204
205     def set_value(self, value):
206         if type(value) is not list:
207             value = [value]
208         for val in value:
209             if type(val) is not tuple:
210                 val = (val, True)
211             if val[0] not in self._allowed_values:
212                 raise ValueError(
213                     'Value "%s" not allowed [%s]' % (val[0],
214                                                      self._allowed_values))
215             if val[1] is True:
216                 if val[0] not in self._assigned_value:
217                     self._assigned_value.append(val[0])
218             else:
219                 if val[0] in self._assigned_value:
220                     self._assigned_value.remove(val[0])
221
222     def unset_value(self, value):
223         if type(value) is str:
224             value = [value]
225         unset = list()
226         for val in value:
227             unset.append((val, False))
228         self.set_value(unset)
229
230     def get_allowed(self):
231         return self._allowed_values
232
233     def export_value(self):
234         enabled = self.get_value()
235         return ', '.join(enabled)
236
237     def import_value(self, value):
238         enabled = [x.strip() for x in value.split(',')]
239         for val in enabled:
240             if val not in self._allowed_values:
241                 # We silently ignore invalid options on import for now
242                 continue
243             self._assigned_value[val] = True
244
245
246 class Pick(Option):
247
248     def __init__(self, name, description, allowed, default_value):
249         super(Pick, self).__init__(name, description)
250         self._allowed_values = list(allowed)
251         if default_value not in self._allowed_values:
252             raise ValueError('The default value is not in the allowed list')
253         self._default_value = default_value
254
255     def set_value(self, value):
256         if value not in self._allowed_values:
257             raise ValueError(
258                 'Value "%s" not allowed [%s]' % (value, self._allowed_values))
259         self._assigned_value = value
260
261     def get_allowed(self):
262         return self._allowed_values
263
264     def export_value(self):
265         return self._str_export_value()
266
267     def import_value(self, value):
268         self._str_import_value(value)
269
270
271 class Condition(Option):
272
273     def __init__(self, name, description, default_value=False):
274         super(Condition, self).__init__(name, description)
275         self._default_value = default_value
276
277     def set_value(self, value):
278         if value is True:
279             self._assigned_value = True
280         elif value is False:
281             self._assigned_value = False
282         else:
283             raise ValueError('Value must be True or False, got %s' % value)
284
285     def export_value(self):
286         if self._assigned_value is True:
287             return '1'
288         elif self._assigned_value is False:
289             return '0'
290         else:
291             return None
292
293     def import_value(self, value):
294         if value in ['1', 'YES']:
295             self._assigned_value = True
296         else:
297             self._assigned_value = False