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