Add defaults to List objects
[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         else:
163             self._default_value = []
164
165     def set_value(self, value):
166         self._assigned_value = list(value)
167
168     def export_value(self):
169         if self._assigned_value:
170             return ','.join(self._assigned_value)
171         return None
172
173     def import_value(self, value):
174         if type(value) is not str:
175             raise ValueError('Value (type: %s) must be string' % type(value))
176         self._assigned_value = [x.strip() for x in value.split(',')]
177
178
179 class Choice(Option):
180
181     def __init__(self, name, description, allowed=None, default=None):
182         super(Choice, self).__init__(name, description)
183         if allowed:
184             self._allowed_values = list(allowed)
185         else:
186             self._allowed_values = list()
187         self._default_value = list()
188         if default is None:
189             default = []
190         for name in default:
191             if name not in self._allowed_values:
192                 raise ValueError(
193                     'item [%s] is not in allowed [%s]' % (name, allowed))
194             self._default_value.append(name)
195
196     def __repr__(self):
197         return "%s: %s {%s}, values = %s d:%s ok:%s" % (self.__class__,
198                                                         self.name,
199                                                         self.description,
200                                                         self._assigned_value,
201                                                         self._default_value,
202                                                         self._allowed_values)
203
204     def __str__(self):
205         return '%s=%s' % (self.name, self.get_value())
206
207     def set_value(self, value):
208         if type(value) is not list:
209             value = [value]
210         self._assigned_value = list()
211         for val in value:
212             if val not in self._allowed_values:
213                 raise ValueError(
214                     'Value "%s" not allowed [%s]' % (val,
215                                                      self._allowed_values))
216             self._assigned_value.append(val)
217
218         if not self._assigned_value:
219             self._assigned_value = None
220
221     def unset_value(self, value):
222         if type(value) is str:
223             value = [value]
224         unset = list()
225         for val in value:
226             unset.append((val, False))
227         self.set_value(unset)
228
229     def get_allowed(self):
230         return self._allowed_values
231
232     def export_value(self):
233         enabled = self.get_value()
234         return ', '.join(enabled)
235
236     def import_value(self, value):
237         enabled = [x.strip() for x in value.split(',')]
238         if enabled:
239             if self._assigned_value is None:
240                 self._assigned_value = list()
241         for val in enabled:
242             if val not in self._allowed_values:
243                 # We silently ignore invalid options on import for now
244                 continue
245             self._assigned_value.append(val)
246
247
248 class Pick(Option):
249
250     def __init__(self, name, description, allowed, default_value):
251         super(Pick, self).__init__(name, description)
252         self._allowed_values = list(allowed)
253         if default_value not in self._allowed_values:
254             raise ValueError('The default value is not in the allowed list')
255         self._default_value = default_value
256
257     def set_value(self, value):
258         if value not in self._allowed_values:
259             raise ValueError(
260                 'Value "%s" not allowed [%s]' % (value, self._allowed_values))
261         self._assigned_value = value
262
263     def get_allowed(self):
264         return self._allowed_values
265
266     def export_value(self):
267         return self._str_export_value()
268
269     def import_value(self, value):
270         self._str_import_value(value)
271
272
273 class Condition(Pick):
274
275     def __init__(self, name, description, default_value=False):
276         super(Condition, self).__init__(name, description,
277                                         [True, False], default_value)
278
279     def import_value(self, value):
280         self._assigned_value = value == 'True'